dataclasses
— Data Classes数据类¶
Source code: Lib/dataclasses.py
This module provides a decorator and functions for automatically adding generated special methods such as 该模块提供了一个装饰器和函数,用于自动向用户定义的类添加生成的特殊方法,如__init__()
and __repr__()
to user-defined classes. __init__()
和__repr__()
。It was originally described in PEP 557.最初在PEP 557中进行了描述。
The member variables to use in these generated methods are defined using PEP 526 type annotations. 在这些生成的方法中使用的成员变量是使用PEP 526类型注释定义的。For example, this code:例如,此代码:
from dataclasses import dataclass
@dataclass
class InventoryItem:
"""Class for keeping track of an item in inventory."""
name: str
unit_price: float
quantity_on_hand: int = 0
def total_cost(self) -> float:
return self.unit_price * self.quantity_on_hand
will add, among other things, a 将添加一个__init__()
that looks like:__init__()
,看起来像:
def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0):
self.name = name
self.unit_price = unit_price
self.quantity_on_hand = quantity_on_hand
Note that this method is automatically added to the class: it is not directly specified in the 请注意,此方法将自动添加到类中:它不是在上面显示的InventoryItem
definition shown above.InventoryItem
定义中直接指定的。
New in version 3.7.版本3.7中新增。
Module contents模块内容¶
-
@
dataclasses.
dataclass
(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False)¶ This function is a decorator that is used to add generated special methods to classes, as described below.此函数是一个装饰器,用于将生成的特殊方法添加到类中,如下所述。Thedataclass()
decorator examines the class to findfield
s.dataclass()
修饰符检查类以查找field
。Afield
is defined as a class variable that has a type annotation.field
定义为具有类型注释的类变量。With two exceptions described below, nothing in除了下面描述的两个例外,dataclass()
examines the type specified in the variable annotation.dataclass()
中没有检查变量注释中指定的类型。The order of the fields in all of the generated methods is the order in which they appear in the class definition.所有生成的方法中字段的顺序是它们在类定义中出现的顺序。Thedataclass()
decorator will add various “dunder” methods to the class, described below.dataclass()
装饰器将向类中添加各种“dunder”方法,如下所述。If any of the added methods already exist in the class, the behavior depends on the parameter, as documented below.如果类中已经存在任何添加的方法,则行为取决于参数,如下所述。The decorator returns the same class that it is called on; no new class is created.装饰器返回其被调用的同一类;不创建新类。If如果dataclass()
is used just as a simple decorator with no parameters, it acts as if it has the default values documented in this signature.dataclass()
只是作为一个没有参数的简单装饰器使用,那么它的行为就好像它具有此签名中记录的默认值一样。That is, these three uses of也就是说,dataclass()
are equivalent:dataclass()
的这三种用法是等价的:@dataclass
class C:
...
@dataclass()
class C:
...
@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False)
class C:
...The parameters todataclass()
are:dataclass()
的参数为:init
: If true (the default), a:如果为__init__()
method will be generated.true
(默认值),将生成__init__()
方法。If the class already defines如果类已定义__init__()
, this parameter is ignored.__init__()
,则忽略此参数。repr
: If true (the default), a:如果为__repr__()
method will be generated.true
(默认值),将生成__repr__()
方法。The generated repr string will have the class name and the name and repr of each field, in the order they are defined in the class.生成的repr字符串将具有类名以及每个字段的名称和repr,按照它们在类中定义的顺序。Fields that are marked as being excluded from the repr are not included.不包括标记为从报告中排除的字段。For example:例如:InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=10)
.If the class already defines如果类已定义__repr__()
, this parameter is ignored.__repr__()
,则忽略此参数。eq
: If true (the default), an:如果为__eq__()
method will be generated.true
(默认值),将生成__eq__()
方法。This method compares the class as if it were a tuple of its fields, in order.该方法按顺序将类作为其字段的元组进行比较。Both instances in the comparison must be of the identical type.比较中的两个实例必须是相同的类型。If the class already defines如果类已定义__eq__()
, this parameter is ignored.__eq__()
,则忽略此参数。order
: If true (the default is:如果为False
),__lt__()
,__le__()
,__gt__()
, and__ge__()
methods will be generated.true
(默认值为False
),将生成__lt__()
、__le__()
,__gt__()
和__ge__()
方法。These compare the class as if it were a tuple of its fields, in order.它们将类作为其字段的元组,按顺序进行比较。Both instances in the comparison must be of the identical type.比较中的两个实例必须是相同的类型。If如果order
is true andeq
is false, aValueError
is raised.order
为true
,eq
为false
,则会引发ValueError
。If the class already defines any of如果该类已经定义了__lt__()
,__le__()
,__gt__()
, or__ge__()
, thenTypeError
is raised.__lt__()
、__le__()
、__gt__()
或__ge__()
,则会引发TypeError
。unsafe_hash
: If:如果为False(默认值),将根据False
(the default), a__hash__()
method is generated according to howeq
andfrozen
are set.eq
和frozen
的设置生成__hash__()
方法。__hash__()
is used by built-inhash()
, and when objects are added to hashed collections such as dictionaries and sets.__hash__()
由内置的hash()
使用,当对象被添加到哈希集合(如字典和集合)中时。Having a拥有__hash__()
implies that instances of the class are immutable.__hash__()
意味着类的实例是不可变的。Mutability is a complicated property that depends on the programmer’s intent, the existence and behavior of可变性是一个复杂的属性,它取决于程序员的意图、__eq__()
, and the values of theeq
andfrozen
flags in thedataclass()
decorator.__eq__()
的存在和行为,以及dataclass()
修饰符中eq
和frozen
标志的值。By default,默认情况下,dataclass()
will not implicitly add a__hash__()
method unless it is safe to do so.dataclass()
不会隐式添加__hash__()
方法,除非这样做是安全的。Neither will it add or change an existing explicitly defined它也不会添加或更改现有的显式定义的__hash__()
method.__hash__()
方法。Setting the class attribute设置类属性__hash__ = None
has a specific meaning to Python, as described in the__hash__()
documentation.__hash__=None
对Python有特定意义,如__hash__()
文档中所述。If如果__hash__()
is not explicitly defined, or if it is set toNone
, thendataclass()
may add an implicit__hash__()
method.__hash__()
未显式定义,或者设置为None
,则dataclass()
可以添加隐式__hash__()
方法。Although not recommended, you can force虽然不建议使用,但可以强制dataclass()
to create a__hash__()
method withunsafe_hash=True
.dataclass()
创建一个__hash__()
方法,其中unsafe_hash=True
。This might be the case if your class is logically immutable but can nonetheless be mutated.如果您的类在逻辑上是不可变的,但仍然可以进行变异,则可能会出现这种情况。This is a specialized use case and should be considered carefully.这是一个专门的用例,应该仔细考虑。Here are the rules governing implicit creation of a以下是控制__hash__()
method.__hash__()
方法隐式创建的规则。Note that you cannot both have an explicit请注意,不能在数据类中同时使用显式__hash__()
method in your dataclass and setunsafe_hash=True
; this will result in aTypeError
.__hash__()
方法并设置unsafe_hash=True
;这将导致TypeError
。If如果eq
andfrozen
are both true, by defaultdataclass()
will generate a__hash__()
method for you.eq
和freeze
都为dataclass()
,默认情况下dataclass()
将为您生成__hash__()
方法。If如果eq
is true andfrozen
is false,__hash__()
will be set toNone
, marking it unhashable (which it is, since it is mutable).eq
为true
,而frozen
为false
,__hash__()
将设置为None
,将其标记为不可更改(因为它是可变的)。If如果eq
is false,__hash__()
will be left untouched meaning the__hash__()
method of the superclass will be used (if the superclass isobject
, this means it will fall back to id-based hashing).eq
为false
,__hash__()
将保持不变,这意味着将使用超类的__hash__()
方法(如果超类是object
,则意味着它将返回到基于id的哈希)。frozen
: If true (the default is:如果为False
), assigning to fields will generate an exception.true
(默认为False
),则分配给字段将生成异常。This emulates read-only frozen instances.这将模拟只读冻结实例。If如果在类中定义了__setattr__()
or__delattr__()
is defined in the class, thenTypeError
is raised.__setattr__()
或__delatt__()
,则引发TypeError
。See the discussion below.请参阅下面的讨论。match_args
: If true (the default is:如果为True
), the__match_args__
tuple will be created from the list of parameters to the generated__init__()
method (even if__init__()
is not generated, see above).true
(默认值为true
),__match_args__
元组将从参数列表创建到生成的__init__()
方法(即使未生成__init__()
),请参阅上文)。If false, or if如果为__match_args__
is already defined in the class, then__match_args__
will not be generated.false
,或者类中已经定义了__match_args__
,则不会生成__match_args__
。
New in version 3.10.版本3.10中新增。kw_only
: If true (the default value is:如果为False
), then all fields will be marked as keyword-only.true
(默认值为False
),则所有字段都将标记为仅关键字。If a field is marked as keyword-only, then the only affect is that the如果字段被标记为仅关键字,则唯一的影响是,在调用__init__()
parameter generated from a keyword-only field must be specified with a keyword when__init__()
is called.__init__()
时,从仅关键字字段生成的__init__()
参数必须用关键字指定。There is no effect on any other aspect of dataclasses.对数据类的任何其他方面都没有影响。See the parameter glossary entry for details.有关详细信息,请参阅参数词汇表条目。Also see the另请参见KW_ONLY
section.KW_ONLY
部分。
New in version 3.10.版本3.10中新增。slots
: If true (the default is:如果为False
),__slots__
attribute will be generated and new class will be returned instead of the original one.true
(默认为False
),将生成__slots__
属性,并返回新类而不是原始类。If如果类中已定义__slots__
is already defined in the class, thenTypeError
is raised.__slots__
,则会引发TypeError
。
New in version 3.10.版本3.10中新增。field
s may optionally specify a default value, using normal Python syntax:可以使用常规Python语法指定默认值:@dataclass
class C:
a: int # 'a' has no default value
b: int = 0 # assign a default value for 'b'In this example, both在本例中,a
andb
will be included in the added__init__()
method, which will be defined as:a
和b
都将包含在添加的__init__()
方法中,该方法将定义为:def __init__(self, a: int, b: int = 0):
TypeError
will be raised if a field without a default value follows a field with a default value.如果没有默认值的字段跟在具有默认值的域之后,将引发。This is true whether this occurs in a single class, or as a result of class inheritance.无论这发生在单个类中,还是作为类继承的结果,都是如此。
-
dataclasses.
field
(*, default=MISSING, default_factory=MISSING, init=True, repr=True, hash=None, compare=True, metadata=None, kw_only=MISSING)¶ For common and simple use cases, no other functionality is required.对于常见和简单的用例,不需要其他功能。There are, however, some dataclass features that require additional per-field information.但是,有些数据类功能需要额外的每个字段信息。To satisfy this need for additional information, you can replace the default field value with a call to the provided为了满足对附加信息的需求,您可以通过调用提供的field()
function.field()
函数来替换默认字段值。For example:例如:@dataclass
class C:
mylist: list[int] = field(default_factory=list)
c = C()
c.mylist += [1, 2, 3]As shown above, the如上所示,MISSING
value is a sentinel object used to detect if some parameters are provided by the user.MISSING
值是一个哨兵对象,用于检测用户是否提供了某些参数。This sentinel is used because之所以使用此sentinel,是因为None对于某些具有不同含义的参数是有效值。None
is a valid value for some parameters with a distinct meaning.No code should directly use the任何代码都不应直接使用MISSING
value.MISSING
值。The parameters tofield()
are:field()
的参数如下:default
: If provided, this will be the default value for this field.:如果提供,这将是此字段的默认值。This is needed because the这是必需的,因为field()
call itself replaces the normal position of the default value.field()
调用本身会替换默认值的正常位置。default_factory
: If provided, it must be a zero-argument callable that will be called when a default value is needed for this field.:如果提供,则它必须是一个零参数可调用,当此字段需要默认值时将调用该参数。Among other purposes, this can be used to specify fields with mutable default values, as discussed below.除其他目的外,这可以用于指定具有可变默认值的字段,如下所述。It is an error to specify both同时指定default
anddefault_factory
.default
和default_factory
是错误的。init
: If true (the default), this field is included as a parameter to the generated:如果为__init__()
method.true
(默认值),则此字段作为生成的__init__()
方法的参数包含。repr
: If true (the default), this field is included in the string returned by the generated:如果为__repr__()
method.true
(默认值),则此字段包含在生成的__repr_()
方法返回的字符串中。hash
: This can be a bool or:这可以是bool或None
.None
。If true, this field is included in the generated如果为__hash__()
method.true
,则此字段包含在生成的__hash__()
方法中。If如果None
(the default), use the value ofcompare
: this would normally be the expected behavior.None
(默认值),则使用compare
的值:这通常是预期的行为。A field should be considered in the hash if it’s used for comparisons.如果用于比较,则应在哈希中考虑字段。Setting this value to anything other than不建议将此值设置为None
is discouraged.None
以外的任何值。One possible reason to set设置hash=False
butcompare=True
would be if a field is expensive to compute a hash value for, that field is needed for equality testing, and there are other fields that contribute to the type’s hash value.hash=False
但compare=True
的一个可能原因是,如果一个字段计算哈希值的成本很高,该字段需要进行相等测试,并且还有其他字段对该类型的哈希值有贡献。Even if a field is excluded from the hash, it will still be used for comparisons.即使字段从哈希中排除,它仍将用于比较。compare
: If true (the default), this field is included in the generated equality and comparison methods (:如果为__eq__()
,__gt__()
, et al.).true
(默认值),则此字段包含在生成的相等和比较方法(__eq__()
、__gt__()
等)中。metadata
: This can be a mapping or None. None is treated as an empty dict.:这可以是映射或无。没有一个被视为空字典。This value is wrapped in该值被包装在MappingProxyType()
to make it read-only, and exposed on theField
object.MappingProxyType()
中以使其只读,并在Field
对象上公开。It is not used at all by Data Classes, and is provided as a third-party extension mechanism.数据类根本不使用它,而是作为第三方扩展机制提供的。Multiple third-parties can each have their own key, to use as a namespace in the metadata.多个第三方可以各自拥有自己的密钥,用作元数据中的命名空间。kw_only
: If true, this field will be marked as keyword-only.:如果为true
,则此字段将仅标记为关键字。This is used when the generated这在计算生成的__init__()
method’s parameters are computed.__init__()
方法的参数时使用。
New in version 3.10.版本3.10中新增。If the default value of a field is specified by a call to如果通过调用field()
, then the class attribute for this field will be replaced by the specifieddefault
value.field()
指定字段的默认值,则该字段的class属性将被指定的default
值替换。If no如果未提供default
is provided, then the class attribute will be deleted.default
,则将删除class属性。The intent is that after the其目的是在dataclass()
decorator runs, the class attributes will all contain the default values for the fields, just as if the default value itself were specified.dataclass()
装饰器运行后,类属性将全部包含字段的默认值,就像指定了默认值一样。For example, after:例如,在:@dataclass
class C:
x: int
y: int = field(repr=False)
z: int = field(repr=False, default=10)
t: int = 20The class attribute类属性C.z
will be10
, the class attributeC.t
will be20
, and the class attributesC.x
andC.y
will not be set.C.z
将为10
,类属性C.t
将为20
,并且不设置类属性C.x
和C.y
。
-
class
dataclasses.
Field
¶ Field
objects describe each defined field.对象描述每个定义的字段。These objects are created internally, and are returned by the这些对象是在内部创建的,并由fields()
module-level method (see below).fields()
模块级方法返回(见下文)。Users should never instantiate a用户不应直接实例化Field
object directly.Field
对象。Its documented attributes are:其记录属性包括:name
: The name of the field.:字段的名称。type
: The type of the field.:字段的类型。default
,default_factory
,init
,repr
,hash
,compare
,metadata
, andkw_only
have the identical meaning and values as they do in thefield()
function.default
、default_factory
、init
、repr
、hash
、compare
、metadata
和kw_only
具有与field()
函数中相同的含义和值。
Other attributes may exist, but they are private and must not be inspected or relied on.其他属性可能存在,但它们是私有的,不得检查或依赖。
-
dataclasses.
fields
(class_or_instance)¶ Returns a tuple of返回定义此数据类的字段的Field
objects that define the fields for this dataclass.Field
对象的元组。Accepts either a dataclass, or an instance of a dataclass.接受数据类或数据类的实例。Raises如果未传递数据类或数据类的实例,则引发TypeError
if not passed a dataclass or instance of one.TypeError
。Does not return pseudo-fields which are不返回ClassVar
orInitVar
.ClassVar
或InitVar
的伪字段。
-
dataclasses.
asdict
(obj, *, dict_factory=dict)¶ Converts the dataclass将数据类obj
to a dict (by using the factory functiondict_factory
).obj
转换为dict(通过使用工厂函数dict_factory
)。Each dataclass is converted to a dict of its fields, as每个数据类都转换为其字段的dict,如name: value
pairs.name: value
对。dataclasses, dicts, lists, and tuples are recursed into.数据类、字典、列表和元组被递归到。Other objects are copied with使用copy.deepcopy()
.copy.deepcopy()
复制其他对象。Example of using在嵌套数据类上使用asdict()
on nested dataclasses:asdict()
的示例:@dataclass
class Point:
x: int
y: int
@dataclass
class C:
mylist: list[Point]
p = Point(10, 20)
assert asdict(p) == {'x': 10, 'y': 20}
c = C([Point(0, 0), Point(10, 4)])
assert asdict(c) == {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]}To create a shallow copy, the following workaround may be used:要创建浅层副本,可以使用以下解决方法:dict((field.name, getattr(obj, field.name)) for field in fields(obj))
如果asdict()
raisesTypeError
ifobj
is not a dataclass instance.obj
不是数据类实例,asdict()
将引发TypeError
。
-
dataclasses.
astuple
(obj, *, tuple_factory=tuple)¶ Converts the dataclass将数据类obj
to a tuple (by using the factory functiontuple_factory
).obj
转换为元组(通过使用工厂函数tuple_factory
)。Each dataclass is converted to a tuple of its field values. dataclasses, dicts, lists, and tuples are recursed into.每个数据类都转换为其字段值的元组。数据类、字典、列表和元组被递归到。Other objects are copied with使用copy.deepcopy()
.copydeepcopy()
复制其他对象。Continuing from the previous example:继续上一示例:assert astuple(p) == (10, 20)
assert astuple(c) == ([(0, 0), (10, 4)],)To create a shallow copy, the following workaround may be used:要创建浅层副本,可以使用以下解决方法:tuple(getattr(obj, field.name) for field in dataclasses.fields(obj))
如果astuple()
raisesTypeError
ifobj
is not a dataclass instance.obj
不是数据类实例,astuple()
将引发TypeError
。
-
dataclasses.
make_dataclass
(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False)¶ Creates a new dataclass with name创建一个名为cls_name
, fields as defined infields
, base classes as given inbases
, and initialized with a namespace as given innamespace
.cls_name
、fields
中定义的字段、bases
中给定的基类,并用命名空间中给定的namespace
初始化。fields
is an iterable whose elements are each eithername
,(name, type)
, or(name, type, Field)
.fields
是一个可迭代的元素,其元素分别为name
、(name, type)
或(name, type, Field)
。If just如果只提供name
is supplied,typing.Any
is used fortype
.name
,则typing.Any
用于type
。The values ofinit
,repr
,eq
,order
,unsafe_hash
,frozen
,match_args
,kw_only
, andslots
have the same meaning as they do indataclass()
.init
、repr
、eq
、order
、unsafehash
、freeze
、match_args
、kw_only
和slots
的值与dataclass()
中的值具有相同的含义。This function is not strictly required, because any Python mechanism for creating a new class with这个函数并不是严格要求的,因为任何Python机制都可以使用__annotations__
can then apply thedataclass()
function to convert that class to a dataclass.__annotations__
创建新类,然后可以应用dataclass()
函数将该类转换为数据类。This function is provided as a convenience.提供此功能是为了方便。For example:例如:C = make_dataclass('C',
[('x', int),
'y',
('z', int, field(default=5))],
namespace={'add_one': lambda self: self.x + 1})Is equivalent to:相当于:@dataclass
class C:
x: int
y: 'typing.Any'
z: int = 5
def add_one(self):
return self.x + 1
-
dataclasses.
replace
(obj, /, **changes)¶ Creates a new object of the same type as创建一个与obj
, replacing fields with values fromchanges
.obj
类型相同的新对象,用changes
后的值替换字段。If如果obj不是数据类,则引发obj
is not a Data Class, raisesTypeError
.TypeError
。If values in如果changes
do not specify fields, raisesTypeError
.changes
中的值未指定字段,则引发TypeError
。The newly returned object is created by calling the新返回的对象是通过调用数据类的__init__()
method of the dataclass.__init__()
方法创建的。This ensures that这确保__post_init__()
, if present, is also called.__post_init__()
(如果存在)也被调用。Init-only variables without default values, if any exist, must be specified on the call to只有Init没有默认值的变量(如果存在)必须在对replace()
so that they can be passed to__init__()
and__post_init__()
.replace()
的调用中指定,以便将它们传递给__Init__()
和__post_Init__()
。It is an error for如果changes
to contain any fields that are defined as havinginit=False
.changes
包含定义为具有init=False
的任何字段,则是错误的。A在这种情况下,将引发ValueError
will be raised in this case.ValueError
。Be forewarned about how在调用init=False
fields work during a call toreplace()
.replace()
时,请预先警告init=False
字段是如何工作的。They are not copied from the source object, but rather are initialized in它们不是从源对象复制的,而是在__post_init__()
, if they’re initialized at all.__post_init__()
中初始化的(如果它们已经初始化)。It is expected that预计init=False
fields will be rarely and judiciously used.init=False
字段将很少且明智地使用。If they are used, it might be wise to have alternate class constructors, or perhaps a custom如果使用了它们,最好使用替代类构造函数,或者使用一个处理实例复制的自定义replace()
(or similarly named) method which handles instance copying.replace()
(或类似名称)方法。
-
dataclasses.
is_dataclass
(obj)¶ Return如果其参数是dataclass或dataclass的实例,则返回True
if its parameter is a dataclass or an instance of one, otherwise returnFalse
.True
,否则返回False
。If you need to know if a class is an instance of a dataclass (and not a dataclass itself), then add a further check for如果您需要知道某个类是否是dataclass的实例(而不是dataclass本身),则需要进一步检查not isinstance(obj, type)
:not isinstance(obj, type)
:def is_dataclass_instance(obj):
return is_dataclass(obj) and not isinstance(obj, type)
-
dataclasses.
MISSING
¶ A sentinel value signifying a missing default or default_factory.表示缺少默认值或default_factory的前哨值。
-
dataclasses.
KW_ONLY
¶ A sentinel value used as a type annotation.用作类型注释的哨兵值。Any fields after a pseudo-field with the type of类型为KW_ONLY
are marked as keyword-only fields.KW_ONLY
的伪字段之后的任何字段都标记为仅关键字字段。Note that a pseudo-field of type请注意,否则将完全忽略KW_ONLY
is otherwise completely ignored.KW_ONLY
类型的伪字段。This includes the name of such a field.这包括此类字段的名称。By convention, a name of按照惯例,名称_
is used for aKW_ONLY
field._
用于KW_ONLY
字段。Keyword-only fields signify仅关键字字段表示__init__()
parameters that must be specified as keywords when the class is instantiated.__init__()
参数,这些参数在实例化类时必须指定为关键字。In this example, the fields在本例中,字段y
andz
will be marked as keyword-only fields:y
和z
将标记为仅关键字字段:@dataclass
class Point:
x: float
_: KW_ONLY
y: float
z: float
p = Point(0, y=1.5, z=2.0)In a single dataclass, it is an error to specify more than one field whose type is在单个数据类中,指定多个类型为KW_ONLY
.KW_ONLY
的字段是错误的。New in version 3.10.版本3.10中新增。
-
exception
dataclasses.
FrozenInstanceError
¶ Raised when an implicitly defined当对定义为__setattr__()
or__delattr__()
is called on a dataclass which was defined withfrozen=True
.frozen=True
的数据类调用隐式定义的__setattr__()
或__delatt__()
时引发。It is a subclass of它是AttributeError
.AttributeError
的子类。
Post-init processing初始化后处理¶
The generated 如果在类上定义了__init__()
code will call a method named __post_init__()
, if __post_init__()
is defined on the class. __post_init__()
,则生成的__init__()
代码将调用名为__post_init__()
的方法。It will normally be called as 它通常被称为self.__post_init__()
. self.__post_init__()
。However, if any 但是,如果定义了任何InitVar
fields are defined, they will also be passed to __post_init__()
in the order they were defined in the class. InitVar
字段,它们也将按照在类中定义的顺序传递给__post_init__()
。If no 如果未生成__init__()
method is generated, then __post_init__()
will not automatically be called.__init__()
方法,则不会自动调用__post_init__()
。
Among other uses, this allows for initializing field values that depend on one or more other fields. 在其他用途中,这允许初始化依赖于一个或多个其他字段的字段值。For example:例如:
@dataclass
class C:
a: float
b: float
c: float = field(init=False)
def __post_init__(self):
self.c = self.a + self.b
The __init__()
method generated by dataclass()
does not call base class __init__()
methods. dataclass()
生成的__init__()
方法不调用基类__init__()
方法。If the base class has an 如果基类具有必须调用的__init__()
method that has to be called, it is common to call this method in a __post_init__()
method:__init__()
方法,则通常在__post_init__()
中调用此方法:
@dataclass
class Rectangle:
height: float
width: float
@dataclass
class Square(Rectangle):
side: float
def __post_init__(self):
super().__init__(self.side, self.side)
Note, however, that in general the dataclass-generated 然而,请注意,通常不需要调用数据类生成的__init__()
methods don’t need to be called, since the derived dataclass will take care of initializing all fields of any base class that is a dataclass itself.__init__()
方法,因为派生的数据类将负责初始化任何基类的所有字段,而基类本身就是一个数据类。
See the section below on init-only variables for ways to pass parameters to 有关将参数传递给__post_init__()
. __post_init__()
的方法,请参阅下面关于仅初始化变量的部分。Also see the warning about how 另请参见有关replace()
handles init=False
fields.replace()
如何处理init=False
字段的警告。
Class variables类变量¶
One of two places where dataclass()
actually inspects the type of a field is to determine if a field is a class variable as defined in PEP 526. dataclass()
实际检查字段类型的两个地方之一是确定字段是否是PEP 526中定义的类变量。It does this by checking if the type of the field is 它通过检查字段的类型是否为typing.ClassVar
. typing.ClassVar
来完成此操作。If a field is a 如果某个字段是ClassVar
, it is excluded from consideration as a field and is ignored by the dataclass mechanisms. ClassVar
,则将其作为字段排除在外,并被数据类机制忽略。Such 模块级ClassVar
pseudo-fields are not returned by the module-level fields()
function.fields()
函数不会返回此类ClassVar
伪字段。
Init-only variables仅初始化变量¶
The other place where dataclass()
inspects a type annotation is to determine if a field is an init-only variable. dataclass()
检查类型注释的另一个地方是确定字段是否是仅初始化的变量。It does this by seeing if the type of a field is of type 它通过查看字段的类型是否为dataclasses.InitVar
. dataclasses.InitVar
类型来执行此操作。If a field is an 如果一个字段是InitVar
, it is considered a pseudo-field called an init-only field. InitVar
,则它被认为是一个伪字段,称为仅初始化字段。As it is not a true field, it is not returned by the module-level 由于它不是真字段,因此模块级fields()
function. fields()
函数不会返回它。Init-only fields are added as parameters to the generated 仅初始化字段作为参数添加到生成的__init__()
method, and are passed to the optional __post_init__()
method. They are not otherwise used by dataclasses.__Init__()
方法中,并传递给可选的__post_Init__()
。数据类不使用它们。
For example, suppose a field will be initialized from a database, if a value is not provided when creating the class:例如,如果创建类时未提供值,则假设将从数据库初始化字段:
@dataclass
class C:
i: int
j: int = None
database: InitVar[DatabaseType] = None
def __post_init__(self, database):
if self.j is None and database is not None:
self.j = database.lookup('j')
c = C(10, database=my_database)
In this case, 在这种情况下,fields()
will return Field
objects for i
and j
, but not for database
.fields()
将返回i
和j
的Field
对象,但不返回数据库的Field对象。
Frozen instances冻结实例¶
It is not possible to create truly immutable Python objects. 创建真正不可变的Python对象是不可能的。However, by passing 然而,通过向frozen=True
to the dataclass()
decorator you can emulate immutability. dataclass()
修饰符传递frozen=True
,可以模拟不变性。In that case, dataclasses will add 在这种情况下,数据类将向类中添加__setattr__()
and __delattr__()
methods to the class. __setattr__()
和__delatt__()
方法。These methods will raise a 这些方法在调用时将引发FrozenInstanceError
when invoked.FrozenInstanceError
。
There is a tiny performance penalty when using 使用frozen=True
: __init__()
cannot use simple assignment to initialize fields, and must use object.__setattr__()
.frozen=True
时会有一点性能损失:__init__()
不能使用简单赋值来初始化字段,必须使用对象object.__setattr__()
。
Inheritance继承¶
When the dataclass is being created by the 当dataclass()
decorator, it looks through all of the class’s base classes in reverse MRO (that is, starting at object
) and, for each dataclass that it finds, adds the fields from that base class to an ordered mapping of fields. dataclass()
修饰符创建数据类时,它会反向MRO(即从object
开始)查看该类的所有基类,并为找到的每个数据类将该基类中的字段添加到字段的有序映射中。After all of the base class fields are added, it adds its own fields to the ordered mapping. 添加所有基类字段后,它将自己的字段添加到有序映射中。All of the generated methods will use this combined, calculated ordered mapping of fields. 所有生成的方法都将使用这种组合的、计算出的字段有序映射。Because the fields are in insertion order, derived classes override base classes. 因为字段是按插入顺序排列的,所以派生类重写基类。An example:例如:
@dataclass
class Base:
x: Any = 15.0
y: int = 0
@dataclass
class C(Base):
z: int = 10
x: int = 15
The final list of fields is, in order, 字段的最终列表依次为x
, y
, z
. x
、y
、z
。The final type of x
is int
, as specified in class C
.x
的最终类型是int
,如C
类中所指定的。
The generated 为__init__()
method for C
will look like:C
生成的__init__()
方法如下所示:
def __init__(self, x: int = 15, y: int = 0, z: int = 10):
Re-ordering of keyword-only parameters in __init__()
__init__()
中仅关键字参数的重新排序¶
__init__()
After the parameters needed for 在计算__init__()
are computed, any keyword-only parameters are moved to come after all regular (non-keyword-only) parameters. __init__()
所需的参数后,任何仅关键字的参数都会移动到所有常规(非仅关键字)参数之后。This is a requirement of how keyword-only parameters are implemented in Python: they must come after non-keyword-only parameters.这是Python中如何实现仅关键字参数的一个要求:它们必须在非仅关键字参数之后。
In this example, 在此示例中,Base.y
, Base.w
, and D.t
are keyword-only fields, and Base.x
and D.z
are regular fields:Base.y
、Base.w
和D.t
是仅关键字字段,Base.x
和D.z
是常规字段:
@dataclass
class Base:
x: Any = 15.0
_: KW_ONLY
y: int = 0
w: int = 1
@dataclass
class D(Base):
z: int = 10
t: int = field(kw_only=True, default=0)
The generated 为__init__()
method for D
will look like:D
生成的__init__()
方法如下所示:
def __init__(self, x: Any = 15.0, z: int = 10, *, y: int = 0, w: int = 1, t: int = 0):
Note that the parameters have been re-ordered from how they appear in the list of fields: parameters derived from regular fields are followed by parameters derived from keyword-only fields.请注意,参数已根据它们在字段列表中的显示方式进行了重新排序:从常规字段派生的参数后跟从仅关键字字段派生的。
The relative ordering of keyword-only parameters is maintained in the re-ordered 仅关键字参数的相对排序在重新排序的__init__()
parameter list.__init__()
参数列表中保持。
Default factory functions默认工厂功能¶
If a如果field()
specifies adefault_factory
, it is called with zero arguments when a default value for the field is needed.field()
指定了default_factory
,则当需要字段的默认值时,将使用零参数调用它。For example, to create a new instance of a list, use:例如,要创建列表的新实例,请使用:mylist: list = field(default_factory=list)
If a field is excluded from如果从__init__()
(usinginit=False
) and the field also specifiesdefault_factory
, then the default factory function will always be called from the generated__init__()
function.__init__()
中排除了一个字段(使用init=False
),并且该字段还指定了default_factory
,那么将始终从生成的__init__()
函数中调用默认工厂函数。This happens because there is no other way to give the field an initial value.之所以发生这种情况,是因为没有其他方法可以为字段赋予初始值。
Mutable default values可变默认值¶
Python stores default member variable values in class attributes.Python将默认成员变量值存储在类属性中。Consider this example, not using dataclasses:考虑这个例子,不使用数据类:class C:
x = []
def add(self, element):
self.x.append(element)
o1 = C()
o2 = C()
o1.add(1)
o2.add(2)
assert o1.x == [1, 2]
assert o1.x is o2.x
Note that the two instances of class注意,C
share the same class variablex
, as expected.C
类的两个实例共享相同的类变量x
,正如预期的那样。
Using dataclasses, if this code was valid:使用数据类,如果此代码有效:@dataclass
class D:
x: List = []
def add(self, element):
self.x += element
it would generate code similar to:它将生成类似于以下内容的代码:class D:
x = []
def __init__(self, x=x):
self.x = x
def add(self, element):
self.x += element
assert D().x is D().x
This has the same issue as the original example using class这与使用C
.C
类的原始示例有相同的问题。That is, two instances of class也就是说,在创建类实例时未指定D
that do not specify a value forx
when creating a class instance will share the same copy ofx
.x
值的两个D
类实例将共享x的相同副本。Because dataclasses just use normal Python class creation they also share this behavior.因为数据类只是使用普通的Python类创建,所以它们也共享这种行为。There is no general way for Data Classes to detect this condition.数据类没有检测这种情况的通用方法。Instead, the相反,如果dataclass()
decorator will raise aTypeError
if it detects a default parameter of typelist
,dict
, orset
.dataclass()
装饰器检测到类型list
、dict
或set
的默认参数,它将引发TypeError
。This is a partial solution, but it does protect against many common errors.这是一个部分解决方案,但它确实可以防止许多常见错误。
Using default factory functions is a way to create new instances of mutable types as default values for fields:使用默认工厂函数是创建可变类型的新实例作为字段的默认值的一种方法:@dataclass
class D:
x: list = field(default_factory=list)
assert D().x is not D().x