Skip to content

Commit 2074efb

Browse files
committed
Hopefully the final set of edits.
1 parent 2a00e91 commit 2074efb

File tree

1 file changed

+74
-38
lines changed

1 file changed

+74
-38
lines changed

pep-0557.rst

+74-38
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Type: Standards Track
66
Content-Type: text/x-rst
77
Created: 02-Jun-2017
88
Python-Version: 3.7
9-
Post-History: 08-Sep-2017, 25-Nov-2017
9+
Post-History: 08-Sep-2017, 25-Nov-2017, 30-Nov-2017
1010

1111
Notice for Reviewers
1212
====================
@@ -57,7 +57,7 @@ to the InventoryItem class::
5757
self.unit_price = unit_price
5858
self.quantity_on_hand = quantity_on_hand
5959
def __repr__(self):
60-
return f'InventoryItem(name={self.name!r},unit_price={self.unit_price!r},quantity_on_hand={self.quantity_on_hand!r})'
60+
return f'InventoryItem(name={self.name!r}, unit_price={self.unit_price!r}, quantity_on_hand={self.quantity_on_hand!r})'
6161
def __eq__(self, other):
6262
if other.__class__ is self.__class__:
6363
return (self.name, self.unit_price, self.quantity_on_hand) == (other.name, other.unit_price, other.quantity_on_hand)
@@ -83,7 +83,7 @@ to the InventoryItem class::
8383
return (self.name, self.unit_price, self.quantity_on_hand) >= (other.name, other.unit_price, other.quantity_on_hand)
8484
return NotImplemented
8585

86-
Data Classes saves you from writing and maintaining these functions.
86+
Data Classes saves you from writing and maintaining these methods.
8787

8888
Rationale
8989
=========
@@ -157,11 +157,16 @@ Note that ``__annotations__`` is guaranteed to be an ordered mapping,
157157
in class declaration order. The order of the fields in all of the
158158
generated methods is the order in which they appear in the class.
159159

160+
The ``dataclass`` decorator will add various "dunder" methods to the
161+
class, described below. If any of the added methods already exist on the
162+
class, a ``TypeError`` will be raised. The decorator returns the same
163+
class that is called on: no new class is created.
164+
160165
The ``dataclass`` decorator is typically used with no parameters and
161166
no parentheses. However, it also supports the following logical
162167
signature::
163168

164-
def dataclass(*, init=True, repr=True, eq=True, compare=True, hash=None, frozen=False)
169+
def dataclass(*, init=True, repr=True, eq=True, order=True, hash=None, frozen=False)
165170

166171
If ``dataclass`` is used just as a simple decorator with no
167172
parameters, it acts as if it has the default values documented in this
@@ -175,7 +180,7 @@ signature. That is, these three uses of ``@dataclass`` are equivalent::
175180
class C:
176181
...
177182

178-
@dataclass(init=True, repr=True, eq=True, compare=True, hash=None, frozen=False)
183+
@dataclass(init=True, repr=True, eq=True, order=True, hash=None, frozen=False)
179184
class C:
180185
...
181186

@@ -184,24 +189,23 @@ The parameters to ``dataclass`` are:
184189
- ``init``: If true (the default), a ``__init__`` method will be
185190
generated.
186191

187-
- ``repr``: If true (the default), a ``__repr__`` function will be
192+
- ``repr``: If true (the default), a ``__repr__`` method will be
188193
generated. The generated repr string will have the class name and
189194
the name and repr of each field, in the order they are defined in
190195
the class. Fields that are marked as being excluded from the repr
191196
are not included. For example:
192-
``InventoryItem(name='widget',unit_price=3.0,quantity_on_hand=10)``.
197+
``InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=10)``.
193198

194199
- ``eq``: If true (the default), ``__eq__`` and ``__ne__`` methods
195200
will be generated. These compare the class as if it were a tuple of
196201
its fields, in order. Both instances in the comparison must be of
197202
the identical type.
198203

199-
- ``compare``: If true (the default), ``__lt__``, ``__le__``,
204+
- ``order``: If true (the default), ``__lt__``, ``__le__``,
200205
``__gt__``, and ``__ge__`` methods will be generated. These compare
201206
the class as if it were a tuple of its fields, in order. Both
202207
instances in the comparison must be of the identical type. If
203-
``compare`` is True, then ``eq`` is ignored, and ``__eq__`` and
204-
``__ne__`` will be automatically generated.
208+
``order`` is true and ``eq`` is false, a ``ValueError`` is raised.
205209

206210
- ``hash``: Either a bool or ``None``. If ``None`` (the default), the
207211
``__hash__`` method is generated according to how ``eq`` and
@@ -235,10 +239,14 @@ Python syntax::
235239
b: int = 0 # assign a default value for 'b'
236240

237241
In this example, both ``a`` and ``b`` will be included in the added
238-
``__init__`` function, which will be defined as::
242+
``__init__`` method, which will be defined as::
239243

240244
def __init__(self, a: int, b: int = 0):
241245

246+
``TypeError`` will be raised if a field without a default value
247+
follows a field with a default value. This is true either when this
248+
occurs in a single class, or as a result of class inheritance.
249+
242250
For common and simple use cases, no other functionality is required.
243251
There are, however, some Data Class features that require additional
244252
per-field information. To satisfy this need for additional
@@ -266,10 +274,10 @@ The parameters to ``field()`` are:
266274
specify both ``default`` and ``default_factory``.
267275

268276
- ``init``: If true (the default), this field is included as a
269-
parameter to the generated ``__init__`` function.
277+
parameter to the generated ``__init__`` method.
270278

271279
- ``repr``: If true (the default), this field is included in the
272-
string returned by the generated ``__repr__`` function.
280+
string returned by the generated ``__repr__`` method.
273281

274282
- ``compare``: If True (the default), this field is included in the
275283
generated equality and comparison methods (``__eq__``, ``__gt__``,
@@ -278,10 +286,16 @@ The parameters to ``field()`` are:
278286
- ``hash``: This can be a bool or ``None``. If True, this field is
279287
included in the generated ``__hash__`` method. If ``None`` (the
280288
default), use the value of ``compare``: this would normally be the
281-
expected behavior. A field needs to be considered in the hash if
289+
expected behavior. A field should be considered in the hash if
282290
it's used for comparisons. Setting this value to anything other
283291
than ``None`` is discouraged.
284292

293+
One possible reason to set ``hash=False`` but ``compare=True`` would
294+
be if a field is expensive to compute a hash value for, that field
295+
is needed for equality testing, and there are other fields that
296+
contribute to the type's hash value. Even if a field is excluded
297+
from the hash, it will still be used for comparisons.
298+
285299
- ``metadata``: This can be a mapping or None. None is treated as an
286300
empty dict. This value is wrapped in ``types.MappingProxyType`` to
287301
make it read-only, and exposed on the Field object. It is not used
@@ -291,12 +305,11 @@ The parameters to ``field()`` are:
291305

292306
If the default value of a field is specified by a call to ``field()``,
293307
then the class attribute for this field will be replaced by the
294-
specified ``default`` value, if one is provided in the call to
295-
``field()``. If no ``default`` is provided, then the class attribute
296-
will be deleted. The intent is that after the ``dataclass`` decorator
297-
runs, the class attributes will all contain the default values for the
298-
fields, just as if the default value itself were specified. For
299-
example, after::
308+
specified ``default`` value. If no ``default`` is provided, then the
309+
class attribute will be deleted. The intent is that after the
310+
``dataclass`` decorator runs, the class attributes will all contain
311+
the default values for the fields, just as if the default value itself
312+
were specified. For example, after::
300313

301314
@dataclass
302315
class C:
@@ -322,17 +335,19 @@ object directly. Its documented attributes are:
322335
- ``type``: The type of the field.
323336

324337
- ``default``, ``default_factory``, ``init``, ``repr``, ``hash``,
325-
 ``compare``, and ``metadata`` have the identical meaning as they do
326-
 in the ``field()`` declaration.
338+
``compare``, and ``metadata`` have the identical meaning and values
339+
as they do in the ``field()`` declaration.
327340

328-
Other attributes may exist, but they are private.
341+
Other attributes may exist, but they are private and must not be
342+
inspected or relied on.
329343

330344
post-init processing
331345
--------------------
332346

333347
The generated ``__init__`` code will call a method named
334-
``__post_init__``, if it is defined on the class. It will
335-
be called as ``self.__post_init__()``.
348+
``__post_init__``, if it is defined on the class. It will be called
349+
as ``self.__post_init__()``. If not ``__init__`` method is generated,
350+
then ``__post_init__`` will not automatically be called.
336351

337352
Among other uses, this allows for initializing field values that
338353
depend on one or more other fields. For example::
@@ -355,12 +370,11 @@ Class variables
355370

356371
One place where ``dataclass`` actually inspects the type of a field is
357372
to determine if a field is a class variable as defined in PEP 526. It
358-
does this by checking if the type of the field is of type
359-
``typing.ClassVar``. If a field is a ``ClassVar``, it is excluded
360-
from consideration as a field and is ignored by the Data Class
361-
mechanisms. For more discussion, see [#]_. Such ``ClassVar``
362-
pseudo-fields are not returned by the module-level ``fields()``
363-
function.
373+
does this by checking if the type of the field is ``typing.ClassVar``.
374+
If a field is a ``ClassVar``, it is excluded from consideration as a
375+
field and is ignored by the Data Class mechanisms. For more
376+
discussion, see [#]_. Such ``ClassVar`` pseudo-fields are not
377+
returned by the module-level ``fields()`` function.
364378

365379
Init-only variables
366380
-------------------
@@ -375,7 +389,7 @@ parameters to the generated ``__init__`` method, and are passed to
375389
the optional ``__post_init__`` method. They are not otherwise used
376390
by Data Classes.
377391

378-
For example, suppose a field will be initialized from a database, if a
392+
For example, suppose a field will be initialzed from a database, if a
379393
value is not provided when creating the class::
380394

381395
@dataclass
@@ -730,12 +744,16 @@ parameters. They are passed first to ``__init__`` which passes them
730744
to ``__post_init__`` where user code can use them as needed.
731745

732746
The only real difference between alternate classmethod constructors
733-
and ``InitVar`` pseudo-fields is in object creation. With
734-
``InitVar``s, using ``__init__`` and the module-level ``replace()``
735-
function ``InitVar``'s must always be specified. With alternate
736-
classmethod constructors the additional initialization parameters are
737-
always optional. Which approach is more appropriate will be
738-
application-specific, but both approaches are supported.
747+
and ``InitVar`` pseudo-fields is in regards to required non-field
748+
parameters during object creation. With ``InitVar``s, using
749+
``__init__`` and the module-level ``replace()`` function ``InitVar``'s
750+
must always be specified. Consider the case where a ``context``
751+
object is needed to create an instance, but isn't stored as a field.
752+
With alternate classmethod constructors the ``context`` parameter is
753+
always optional, because you could still create the object by going
754+
through ``__init__`` (unless you suppress its creation). Which
755+
approach is more appropriate will be application-specific, but both
756+
approaches are supported.
739757

740758
Rejected ideas
741759
==============
@@ -783,6 +801,24 @@ see [#]_.
783801
Examples
784802
========
785803

804+
Custom __init__ method
805+
----------------------
806+
807+
Sometimes the generated ``__init__`` method does not suffice. For
808+
example, suppose you wanted to have an object to store ``*args`` and
809+
``**kwargs``::
810+
811+
@dataclass(init=False)
812+
class ArgHolder:
813+
args: List[Any]
814+
kwargs: Mapping[Any, Any]
815+
816+
def __init__(self, *args, **kwargs):
817+
self.args = args
818+
self.kwargs = kwargs
819+
820+
a = ArgHolder(1, 2, three=3)
821+
786822
A complicated example
787823
---------------------
788824

0 commit comments

Comments
 (0)