From cb4c3c72e1c28acd07c03346712e66db1d7bf51c Mon Sep 17 00:00:00 2001 From: Wes Turner Date: Thu, 30 Nov 2017 06:17:14 -0500 Subject: [PATCH 1/2] pep-0557.rst: typos, .. code:: python directives --- pep-0557.rst | 128 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 92 insertions(+), 36 deletions(-) diff --git a/pep-0557.rst b/pep-0557.rst index ab7967b25a7..368d2c5e41a 100644 --- a/pep-0557.rst +++ b/pep-0557.rst @@ -31,13 +31,15 @@ variables with type annotations as defined in PEP 526, "Syntax for Variable Annotations". In this document, such variables are called fields. Using these fields, the decorator adds generated method definitions to the class to support instance initialization, a repr, -comparisons methods, and optionally other methods as described in the +comparison methods, and optionally other methods as described in the Specification_ section. Such a class is called a Data Class, but there's really nothing special about the class: the decorator adds generated methods to the class and returns the same class it was given. -As an example:: +As an example: + +.. code:: python @dataclass class InventoryItem: @@ -50,7 +52,9 @@ As an example:: return self.unit_price * self.quantity_on_hand The ``@dataclass`` decorator will add the equivalent of these methods -to the InventoryItem class:: +to the InventoryItem class: + +.. code:: python def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0) -> None: self.name = name @@ -83,7 +87,7 @@ to the InventoryItem class:: return (self.name, self.unit_price, self.quantity_on_hand) >= (other.name, other.unit_price, other.quantity_on_hand) return NotImplemented -Data Classes saves you from writing and maintaining these methods. +Data Classes save you from writing and maintaining these methods. Rationale ========= @@ -164,13 +168,17 @@ class that is called on: no new class is created. The ``dataclass`` decorator is typically used with no parameters and no parentheses. However, it also supports the following logical -signature:: +signature: + +.. code:: python def dataclass(*, init=True, repr=True, eq=True, order=True, hash=None, frozen=False) 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. That is, these three uses of ``@dataclass`` are equivalent:: +signature. That is, these three uses of ``@dataclass`` are equivalent: + +.. code:: python @dataclass class C: @@ -186,10 +194,10 @@ signature. That is, these three uses of ``@dataclass`` are equivalent:: The parameters to ``dataclass`` are: -- ``init``: If true (the default), a ``__init__`` method will be +- ``init``: If true (the default), an ``__init__`` method will be generated. -- ``repr``: If true (the default), a ``__repr__`` method will be +- ``repr``: If true (the default), an ``__repr__`` method will be generated. 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. Fields that are marked as being excluded from the repr @@ -231,7 +239,9 @@ The parameters to ``dataclass`` are: See the discussion below. ``field``'s may optionally specify a default value, using normal -Python syntax:: +Python syntax: + +.. code:: python @dataclass class C: @@ -239,7 +249,9 @@ Python syntax:: b: int = 0 # assign a default value for 'b' In this example, both ``a`` and ``b`` will be included in the added -``__init__`` method, which will be defined as:: +``__init__`` method, which will be defined as: + +.. code:: python def __init__(self, a: int, b: int = 0): @@ -251,7 +263,9 @@ For common and simple use cases, no other functionality is required. There are, however, some Data Class 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. The signature of ``field()`` is:: +the provided ``field()`` function. The signature of ``field()`` is: + +.. code:: python def field(*, default=_MISSING, default_factory=_MISSING, repr=True, hash=None, init=True, compare=True, metadata=None) @@ -309,7 +323,9 @@ specified ``default`` value. If no ``default`` is provided, then the class attribute will be deleted. 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. For example, after:: +were specified. For example, after: + +.. code:: python @dataclass class C: @@ -350,7 +366,9 @@ as ``self.__post_init__()``. If not ``__init__`` method is generated, then ``__post_init__`` will not automatically be called. Among other uses, this allows for initializing field values that -depend on one or more other fields. For example:: +depend on one or more other fields. For example: + +.. code:: python @dataclass class C: @@ -390,7 +408,9 @@ the optional ``__post_init__`` method. They are not otherwise used by Data Classes. For example, suppose a field will be initialzed from a database, if a -value is not provided when creating the class:: +value is not provided when creating the class: + +.. code:: python @dataclass class C: @@ -431,7 +451,9 @@ 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:: +example: + +.. code:: python @dataclass class Base: @@ -446,7 +468,9 @@ example:: The final list of fields is, in order, ``x``, ``y``, ``z``. The final type of ``x`` is ``int``, as specified in class ``C``. -The generated ``__init__`` method for ``C`` will look like:: +The generated ``__init__`` method for ``C`` will look like: + +.. code:: python def __init__(self, x: int = 15, y: int = 0, z: int = 10): @@ -455,7 +479,9 @@ Default factory functions If a field specifies a ``default_factory``, it is called with zero arguments when a default value for the field is needed. For example, -to create a new instance of a list, use:: +to create a new instance of a list, use: + +.. code:: python l: list = field(default_factory=list) @@ -469,7 +495,9 @@ Mutable default values ---------------------- Python stores default member variable values in class attributes. -Consider this example, not using Data Classes:: +Consider this example, not using Data Classes: + +.. code:: python class C: x = [] @@ -486,7 +514,9 @@ Consider this example, not using Data Classes:: Note that the two instances of class ``C`` share the same class variable ``x``, as expected. -Using Data Classes, *if* this code was valid:: +Using Data Classes, *if* this code was valid: + +.. code:: python @dataclass class D: @@ -494,7 +524,9 @@ Using Data Classes, *if* this code was valid:: def add(self, element): self.x += element -it would generate code similar to:: +it would generate code similar to: + +.. code:: python class D: x = [] @@ -517,7 +549,9 @@ against many common errors. See `Automatically support mutable default values`_ in the Rejected Ideas section for more details. Using default factory functions is a way to create new instances of -mutable types as default values for fields:: +mutable types as default values for fields: + +.. code:: python @dataclass class D: @@ -538,7 +572,9 @@ Module level helper functions ``instance`` to a dict (by using the factory function ``dict_factory``). Each Data Class is converted to a dict of its fields, as name:value pairs. Data Classes, dicts, lists, and tuples - are recursed into. For example:: + are recursed into. For example: + +  .. code:: python @dataclass class Point: @@ -563,7 +599,9 @@ Module level helper functions field values. Data Classes, dicts, lists, and tuples are recursed into. - Continuing from the previous example:: + Continuing from the previous example: + +  .. code:: python assert astuple(p) == (10, 20) assert astuple(c) == ([(0, 0), (10, 4)],) @@ -580,14 +618,18 @@ Module level helper functions strictly required, because any Python mechanism for creating a new class with ``__annotations__`` can then apply the ``dataclass`` function to convert that class to a Data Class. This function is - provided as a convenience. For example:: + provided as a convenience. For example: + + .. code:: python C = make_dataclass('C', [('x', int), ('y', int, field(default=5))], namespace={'add_one': lambda self: self.x + 1}) - Is equivalent to:: + Is equivalent to: + + .. code:: python @dataclass class C: @@ -667,15 +709,19 @@ Why not just use namedtuple? False. - Instances are always iterable, which can make it difficult to add - fields. If a library defines:: + fields. If a library defines: + + .. code:: python - Time = namedtuple('Time', ['hour', 'minute']) - def get_time(): - return Time(12, 0) +   Time = namedtuple('Time', ['hour', 'minute']) +   def get_time(): +       return Time(12, 0) - Then if a user uses this code as:: + Then if a user uses this code as: + +  .. code:: python - hour, minute = get_time() +   hour, minute = get_time() then it would not be possible to add a ``second`` field to ``Time`` without breaking the user's code. @@ -719,7 +765,9 @@ post-init function ``__post_init__`` never took any parameters. The normal way of doing parameterized initialization (and not just with Data Classes) is to provide an alternate classmethod constructor. -For example:: +For example: + +.. code:: python @dataclass class C: @@ -770,7 +818,9 @@ A previous version of this PEP specified that ``init=False`` fields would be copied from the source object to the newly created object after ``__init__`` returned, but that was deemed to be inconsistent with using ``__init__`` and ``__post_init__`` to initialize the new -object. For example, consider this case:: +object. For example, consider this case: + +.. code:: python @dataclass class Square: @@ -806,7 +856,9 @@ Custom __init__ method Sometimes the generated ``__init__`` method does not suffice. For example, suppose you wanted to have an object to store ``*args`` and -``**kwargs``:: +``**kwargs``: + +.. code:: python @dataclass(init=False) class ArgHolder: @@ -822,7 +874,9 @@ example, suppose you wanted to have an object to store ``*args`` and A complicated example --------------------- -This code exists in a closed source project:: +This code exists in a closed source project: + +.. code:: python class Application: def __init__(self, name, requirements, constraints=None, path='', executable_links=None, executables_dir=()): @@ -837,7 +891,9 @@ This code exists in a closed source project:: def __repr__(self): return f'Application({self.name!r},{self.requirements!r},{self.constraints!r},{self.path!r},{self.executable_links!r},{self.executables_dir!r},{self.additional_items!r})' -This can be replaced by:: +This can be replaced by: + +.. code:: python @dataclass class Application: From 71cef7236d7f4e83eadbfab4dbc58a376b62b1be Mon Sep 17 00:00:00 2001 From: Wes Turner Date: Thu, 30 Nov 2017 07:36:04 -0500 Subject: [PATCH 2/2] pep-0577.rst: an -> a --- pep-0557.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0557.rst b/pep-0557.rst index 368d2c5e41a..62c24067359 100644 --- a/pep-0557.rst +++ b/pep-0557.rst @@ -194,10 +194,10 @@ signature. That is, these three uses of ``@dataclass`` are equivalent: The parameters to ``dataclass`` are: -- ``init``: If true (the default), an ``__init__`` method will be +- ``init``: If true (the default), a ``__init__`` method will be generated. -- ``repr``: If true (the default), an ``__repr__`` method will be +- ``repr``: If true (the default), a ``__repr__`` method will be generated. 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. Fields that are marked as being excluded from the repr