Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Order of non-default dataclass fields when some fields are @property. #102559

Open
Assignees
ericvsmith
Labels
stdlibPython modules in the Lib dirtopic-dataclassestype-bugAn unexpected behavior, bug, or error
@Nuno-Mota

Description

@Nuno-Mota

Bug report

I believe there is an issue with the order in which@dataclass fields are defined when some of those fields have a corresponding@property definition.

MWE:

fromdataclassesimportdataclass,field@dataclassclassA:a:floatb:bool_a:float=field(init=False,repr=False,compare=False)@property# type: ignore[no-redef]defa(self)->float:returnself._a@a.setterdefa(self,new_a:float)->None:# Perform some operation on the new 'a' value (here we sum '100').self._a=new_a+100print(A(3,false))

Running the above example produces the following error:

TypeError: non-default argument 'b' follows default argument

The issue is that when a dataclass is formed it is assumed that any field has a default value if the name corresponding to the field is also an attribute.
Since properties are registered as attributes, this causes the above issue.

One could try to change the order of the fields, such that property fields come after non-property fields.
However, this means that the corresponding property fields do not need to be set when an instance of the class is initialized, which leads to errors later on.
Furthermore, a certain order for the fields might simply make more sense when creating an instance.

I think a simple solution would be to modify the_get_field() function, from:

def_get_field(cls,a_name,a_type,default_kw_only):# Return a Field object for this field name and type.  ClassVars and# InitVars are also returned, but marked as such (see f._field_type).# default_kw_only is the value of kw_only to use if there isn't a field()# that defines it.# If the default value isn't derived from Field, then it's only a# normal default value.  Convert it to a Field().default=getattr(cls,a_name,MISSING)ifisinstance(default,Field):f=defaultelse:ifisinstance(default,types.MemberDescriptorType):# This is a field in __slots__, so it has no default value.default=MISSINGf=field(default=default)    .    .    .

to (or a similar logic, if not this exact structure):

def_get_field(cls,a_name,a_type,default_kw_only):# Return a Field object for this field name and type.  ClassVars and# InitVars are also returned, but marked as such (see f._field_type).# default_kw_only is the value of kw_only to use if there isn't a field()# that defines it.# If the default value isn't derived from Field, then it's only a# normal default value.  Convert it to a Field().default=getattr(cls,a_name,MISSING)ifisinstance(default,Field):f=defaultelse:ifisinstance(default,property):# This field has an attribute, but that attribute is a# @property and not a default value.default=MISSINGelifisinstance(default,types.MemberDescriptorType):# This is a field in __slots__, so it has no default value.default=MISSINGf=field(default=default)    .    .    .

However, I'm not sure if I am missing something that might cause problems.

Let me know if this approach would be good and if I should create a PR for it.

Metadata

Metadata

Assignees

Labels

stdlibPython modules in the Lib dirtopic-dataclassestype-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions


    [8]ページ先頭

    ©2009-2025 Movatter.jp