PEP 520: Preserving Class Attribute Definition Order (round 5)
- a clearer motivation section - include "dunder" names - 2 open questions (__slots__? drop read-only requirement?) -eric ----------------------------------- PEP: 520 Title: Preserving Class Attribute Definition Order Version: $Revision$ Last-Modified: $Date$ Author: Eric Snow <ericsnowcurrently@gmail.com> Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 7-Jun-2016 Python-Version: 3.6 Post-History: 7-Jun-2016, 11-Jun-2016, 20-Jun-2016, 24-Jun-2016 Abstract ======== The class definition syntax is ordered by its very nature. Class attributes defined there are thus ordered. Aside from helping with readability, that ordering is sometimes significant. If it were automatically available outside the class definition then the attribute order could be used without the need for extra boilerplate (such as metaclasses or manually enumerating the attribute order). Given that this information already exists, access to the definition order of attributes is a reasonable expectation. However, currently Python does not preserve the attribute order from the class definition. This PEP changes that by preserving the order in which attributes are introduced in the class definition body. That order will now be preserved in the ``__definition_order__`` attribute of the class. This allows introspection of the original definition order, e.g. by class decorators. Additionally, this PEP changes the default class definition namespace to ``OrderedDict``. The long-lived class namespace (``__dict__``) will remain a ``dict``. Motivation ========== The attribute order from a class definition may be useful to tools that rely on name order. However, without the automatic availability of the definition order, those tools must impose extra requirements on users. For example, use of such a tool may require that your class use a particular metaclass. Such requirements are often enough to discourage use of the tool. Some tools that could make use of this PEP include: * documentation generators * testing frameworks * CLI frameworks * web frameworks * config generators * data serializers * enum factories (my original motivation) Background ========== When a class is defined using a ``class`` statement, the class body is executed within a namespace. Currently that namespace defaults to ``dict``. If the metaclass defines ``__prepare__()`` then the result of calling it is used for the class definition namespace. After the execution completes, the definition namespace namespace is copied into new ``dict``. Then the original definition namespace is discarded. The new copy is stored away as the class's namespace and is exposed as ``__dict__`` through a read-only proxy. The class attribute definition order is represented by the insertion order of names in the *definition* namespace. Thus, we can have access to the definition order by switching the definition namespace to an ordered mapping, such as ``collections.OrderedDict``. This is feasible using a metaclass and ``__prepare__``, as described above. In fact, exactly this is by far the most common use case for using ``__prepare__`` (see PEP 487). At that point, the only missing thing for later access to the definition order is storing it on the class before the definition namespace is thrown away. Again, this may be done using a metaclass. However, this means that the definition order is preserved only for classes that use such a metaclass. There are two practical problems with that: First, it requires the use of a metaclass. Metaclasses introduce an extra level of complexity to code and in some cases (e.g. conflicts) are a problem. So reducing the need for them is worth doing when the opportunity presents itself. PEP 422 and PEP 487 discuss this at length. Given that we now have a C implementation of ``OrderedDict`` and that ``OrderedDict`` is the common use case for ``__prepare__()``, we have such an opportunity by defaulting to ``OrderedDict``. Second, only classes that opt in to using the ``OrderedDict``-based metaclass will have access to the definition order. This is problematic for cases where universal access to the definition order is important. Specification ============= Part 1: * all classes have a ``__definition_order__`` attribute * ``__definition_order__`` is a ``tuple`` of identifiers (or ``None``) * ``__definition_order__`` is a read-only attribute * ``__definition_order__`` is always set: 1. during execution of the class body, the insertion order of names into the class *definition* namespace is stored in a tuple 2. if ``__definition_order__`` is defined in the class body then it must be a ``tuple`` of identifiers or ``None``; any other value will result in ``TypeError`` 3. classes that do not have a class definition (e.g. builtins) have their ``__definition_order__`` set to ``None`` 4. classes for which `__prepare__()`` returned something other than ``OrderedDict`` (or a subclass) have their ``__definition_order__`` set to ``None`` (except where #2 applies) Part 2: * the default class *definition* namespace is now ``OrderdDict`` The following code demonstrates roughly equivalent semantics for the default behavior:: class Meta(type): @classmethod def __prepare__(cls, *args, **kwargs): return OrderedDict() class Spam(metaclass=Meta): ham = None eggs = 5 __definition_order__ = tuple(locals()) Why a tuple? ------------ Use of a tuple reflects the fact that we are exposing the order in which attributes on the class were *defined*. Since the definition is already complete by the time ``__definition_order__`` is set, the content and order of the value won't be changing. Thus we use a type that communicates that state of immutability. Why a read-only attribute? -------------------------- As with the use of tuple, making ``__definition_order__`` a read-only attribute communicates the fact that the information it represents is complete. Since it represents the state of a particular one-time event (execution of the class definition body), allowing the value to be replaced would reduce confidence that the attribute corresponds to the original class body. If a use case for a writable (or mutable) ``__definition_order__`` arises, the restriction may be loosened later. Presently this seems unlikely and furthermore it is usually best to go immutable-by-default. Note that the ability to set ``__definition_order__`` manually allows a dynamically created class (e.g. Cython, ``type()``) to still have ``__definition_order__`` properly set. Why not "__attribute_order__"? ------------------------------ ``__definition_order__`` is centered on the class definition body. The use cases for dealing with the class namespace (``__dict__``) post-definition are a separate matter. ``__definition_order__`` would be a significantly misleading name for a feature focused on more than class definition. Why not ignore "dunder" names? ------------------------------ Names starting and ending with "__" are reserved for use by the interpreter. In practice they should not be relevant to the users of ``__definition_order__``. Instead, for nearly everyone they would only be clutter, causing the same extra work for everyone. However, dropping dunder names by default may inadvertantly cause problems for classes that use dunder names unconventionally. In this case it's better to play it safe and preserve *all* the names from the class definition. Note that a couple of dunder names (``__name__`` and ``__qualname__``) are injected by default by the compiler. So they will be included even though they are not strictly part of the class definition body. Why None instead of an empty tuple? ----------------------------------- A key objective of adding ``__definition_order__`` is to preserve information in class definitions which was lost prior to this PEP. One consequence is that ``__definition_order__`` implies an original class definition. Using ``None`` allows us to clearly distinquish classes that do not have a definition order. An empty tuple clearly indicates a class that came from a definition statement but did not define any attributes there. Why None instead of not setting the attribute? ---------------------------------------------- The absence of an attribute requires more complex handling than ``None`` does for consumers of ``__definition_order__``. Why constrain manually set values? ---------------------------------- If ``__definition_order__`` is manually set in the class body then it will be used. We require it to be a tuple of identifiers (or ``None``) so that consumers of ``__definition_order__`` may have a consistent expectation for the value. That helps maximize the feature's usefulness. We could also also allow an arbitrary iterable for a manually set ``__definition_order__`` and convert it into a tuple. However, not all iterables infer a definition order (e.g. ``set``). So we opt in favor of requiring a tuple. Why is __definition_order__ even necessary? ------------------------------------------- Since the definition order is not preserved in ``__dict__``, it is lost once class definition execution completes. Classes *could* explicitly set the attribute as the last thing in the body. However, then independent decorators could only make use of classes that had done so. Instead, ``__definition_order__`` preserves this one bit of info from the class body so that it is universally available. Support for C-API Types ======================= Arguably, most C-defined Python types (e.g. built-in, extension modules) have a roughly equivalent concept of a definition order. So conceivably ``__definition_order__`` could be set for such types automatically. This PEP does not introduce any such support. However, it does not prohibit it either. The specific cases: * builtin types * PyType_Ready * PyType_FromSpec Compatibility ============= This PEP does not break backward compatibility, except in the case that someone relies *strictly* on ``dict`` as the class definition namespace. This shouldn't be a problem since ``issubclass(OrderedDict, dict)`` is true. Changes ============= In addition to the class syntax, the following expose the new behavior: * builtins.__build_class__ * types.prepare_class * types.new_class Other Python Implementations ============================ Pending feedback, the impact on Python implementations is expected to be minimal. If a Python implementation cannot support switching to `OrderedDict``-by-default then it can always set ``__definition_order__`` to ``None``. Open Questions ============== * What about `__slots__`? * Drop the "read-only attribute" requirement? Per Guido: I don't see why it needs to be a read-only attribute. There are very few of those -- in general we let users play around with things unless we have a hard reason to restrict assignment (e.g. the interpreter's internal state could be compromised). I don't see such a hard reason here. Implementation ============== The implementation is found in the tracker. [impl_] Alternatives ============ An Order-preserving cls.__dict__ -------------------------------- Instead of storing the definition order in ``__definition_order__``, the now-ordered definition namespace could be copied into a new ``OrderedDict``. This would then be used as the mapping proxied as ``__dict__``. Doing so would mostly provide the same semantics. However, using ``OrderedDict`` for ``__dict__`` would obscure the relationship with the definition namespace, making it less useful. Additionally, (in the case of ``OrderedDict`` specifically) doing this would require significant changes to the semantics of the concrete ``dict`` C-API. There has been some discussion about moving to a compact dict implementation which would (mostly) preserve insertion order. However the lack of an explicit ``__definition_order__`` would still remain as a pain point. A "namespace" Keyword Arg for Class Definition ---------------------------------------------- PEP 422 introduced a new "namespace" keyword arg to class definitions that effectively replaces the need to ``__prepare__()``. [pep422_] However, the proposal was withdrawn in favor of the simpler PEP 487. A stdlib Metaclass that Implements __prepare__() with OrderedDict ----------------------------------------------------------------- This has all the same problems as writing your own metaclass. The only advantage is that you don't have to actually write this metaclass. So it doesn't offer any benefit in the context of this PEP. Set __definition_order__ at Compile-time ---------------------------------------- Each class's ``__qualname__`` is determined at compile-time. This same concept could be applied to ``__definition_order__``. The result of composing ``__definition_order__`` at compile-time would be nearly the same as doing so at run-time. Comparative implementation difficulty aside, the key difference would be that at compile-time it would not be practical to preserve definition order for attributes that are set dynamically in the class body (e.g. ``locals()[name] = value``). However, they should still be reflected in the definition order. One posible resolution would be to require class authors to manually set ``__definition_order__`` if they define any class attributes dynamically. Ultimately, the use of ``OrderedDict`` at run-time or compile-time discovery is almost entirely an implementation detail. References ========== .. [impl] issue #24254 (https://bugs.python.org/issue24254) .. [nick_concern] Nick's concerns about mutability (https://mail.python.org/pipermail/python-dev/2016-June/144883.html) .. [pep422] PEP 422 (https://www.python.org/dev/peps/pep-0422/#order-preserving-classes) .. [pep487] PEP 487 (https://www.python.org/dev/peps/pep-0487/#defining-arbitrary-namespaces) .. [orig] original discussion (https://mail.python.org/pipermail/python-ideas/2013-February/019690.html) .. [followup1] follow-up 1 (https://mail.python.org/pipermail/python-dev/2013-June/127103.html) .. [followup2] follow-up 2 (https://mail.python.org/pipermail/python-dev/2015-May/140137.html) Copyright =========== This document has been placed in the public domain.
This version looks fine to me. On 24 June 2016 at 14:52, Eric Snow <ericsnowcurrently@gmail.com> wrote:
Background ==========
When a class is defined using a ``class`` statement, the class body is executed within a namespace. Currently that namespace defaults to ``dict``. If the metaclass defines ``__prepare__()`` then the result of calling it is used for the class definition namespace.
After the execution completes, the definition namespace namespace is copied into new ``dict``. Then the original definition namespace is discarded. The new copy is stored away as the class's namespace and is exposed as ``__dict__`` through a read-only proxy.
The class attribute definition order is represented by the insertion order of names in the *definition* namespace. Thus, we can have access to the definition order by switching the definition namespace to an ordered mapping, such as ``collections.OrderedDict``. This is feasible using a metaclass and ``__prepare__``, as described above. In fact, exactly this is by far the most common use case for using ``__prepare__`` (see PEP 487).
The definition order question has been dropped from PEP 487, so this cross-reference doesn't really make sense any more :)
Part 2:
* the default class *definition* namespace is now ``OrderdDict``
The following code demonstrates roughly equivalent semantics for the default behavior::
class Meta(type): @classmethod def __prepare__(cls, *args, **kwargs): return OrderedDict()
class Spam(metaclass=Meta): ham = None eggs = 5 __definition_order__ = tuple(locals())
I'd characterise this section at the language definition level as the default class definition namespace now being *permitted* to be an OrderedDict. For implementations where dict is ordered by default, there's no requirement to switch specifically to collections.OrderedDict.
Why a read-only attribute? --------------------------
As with the use of tuple, making ``__definition_order__`` a read-only attribute communicates the fact that the information it represents is complete. Since it represents the state of a particular one-time event (execution of the class definition body), allowing the value to be replaced would reduce confidence that the attribute corresponds to the original class body.
If a use case for a writable (or mutable) ``__definition_order__`` arises, the restriction may be loosened later. Presently this seems unlikely and furthermore it is usually best to go immutable-by-default.
Note that the ability to set ``__definition_order__`` manually allows a dynamically created class (e.g. Cython, ``type()``) to still have ``__definition_order__`` properly set.
This paragraph is a little confusing, since "set ``__definition_order__`` manually" is ambiguous. "supply an explicit ``__definition_order__`` via the class namespace" might be clearer.
Why not ignore "dunder" names? ------------------------------
Names starting and ending with "__" are reserved for use by the interpreter. In practice they should not be relevant to the users of ``__definition_order__``. Instead, for nearly everyone they would only be clutter, causing the same extra work for everyone.
However, dropping dunder names by default may inadvertantly cause problems for classes that use dunder names unconventionally. In this case it's better to play it safe and preserve *all* the names from the class definition.
Note that a couple of dunder names (``__name__`` and ``__qualname__``) are injected by default by the compiler. So they will be included even though they are not strictly part of the class definition body.
I realised there's another important reason for doing it this way by default: it's *really easy* to write a "skip_dunder_names" filter that leaves out dunder names from an arbitrary interable of strings. It's flatout *impossible* to restore the dunder attribute order if the class definition process throws it away. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On Fri, Jun 24, 2016 at 4:37 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
This version looks fine to me.
\o/
The definition order question has been dropped from PEP 487, so this cross-reference doesn't really make sense any more :)
Ah, so much for my appeal to authority. <wink>
I'd characterise this section at the language definition level as the default class definition namespace now being *permitted* to be an OrderedDict. For implementations where dict is ordered by default, there's no requirement to switch specifically to collections.OrderedDict.
Yeah, I'd meant to fix that.
This paragraph is a little confusing, since "set ``__definition_order__`` manually" is ambiguous.
"supply an explicit ``__definition_order__`` via the class namespace" might be clearer.
ack
I realised there's another important reason for doing it this way by default: it's *really easy* to write a "skip_dunder_names" filter that leaves out dunder names from an arbitrary interable of strings. It's flatout *impossible* to restore the dunder attribute order if the class definition process throws it away.
Yep. That's why I felt fine with relaxing that. I guess I didn't actually put that in the PEP though. :) -eric
On Fri, Jun 24, 2016 at 3:46 PM, Eric Snow <ericsnowcurrently@gmail.com> wrote:
On Fri, Jun 24, 2016 at 4:37 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
This version looks fine to me.
\o/
Same to me, mostly.
The definition order question has been dropped from PEP 487, so this cross-reference doesn't really make sense any more :)
Ah, so much for my appeal to authority. <wink>
I'd characterise this section at the language definition level as the default class definition namespace now being *permitted* to be an OrderedDict. For implementations where dict is ordered by default, there's no requirement to switch specifically to collections.OrderedDict.
Yeah, I'd meant to fix that.
Please do.
This paragraph is a little confusing, since "set ``__definition_order__`` manually" is ambiguous.
"supply an explicit ``__definition_order__`` via the class namespace" might be clearer.
ack
I realised there's another important reason for doing it this way by default: it's *really easy* to write a "skip_dunder_names" filter that leaves out dunder names from an arbitrary interable of strings. It's flatout *impossible* to restore the dunder attribute order if the class definition process throws it away.
Yep. That's why I felt fine with relaxing that. I guess I didn't actually put that in the PEP though. :)
Please add it. I'd also like the PEP point out that there might be other things that an app wouldn't want in the definition order, e.g. anything that's a method, or anything that starts with '_', etc. I still think that it should not be read-only. If __slots__ and __name__ can be writable I think __definition_order__ can be too. (I believe an easy way to make it so should be to add it to the dict that's passed to type.__new__().) Other nits: - I don't think it's great to let other implementations leave __definition_order__ set to None when they don't care to support it; this would break apps/libraries that want to use it and the implementation could refuse to fix it, claiming PEP 520 doesn't mandate it. I think it's better to mandate this from a confirming implementation. - I don't think there's much of a use case for setting __definition_order__ (to a tuple) for builtin classes. However I do think extension modules should be allowed to set it, in case they are substituting for a previous Python-level class whose users expect this to work. -- --Guido van Rossum (python.org/~guido)
On Sun, Jun 26, 2016 at 5:55 PM, Guido van Rossum <guido@python.org> wrote:
On Fri, Jun 24, 2016 at 4:37 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
This version looks fine to me.
Same to me, mostly.
I've updated the PEP per everyone's comments [1], except I still haven't dropped the read-only __definition_order__ constraint. I'll do that when I resolve the open questions, on which I'd like some feedback: * What about __slots__? In addition to including __slots__ in __definition_order__, the options I see are to either ignore the names in __slots__, put them into __definition_order__ right after __slots__, or stick them in at the end (since their descriptors are added afterward). I'm leaning toward the first one, leaving the slot names out of __definition_order__ since the names aren't actually part of the definition (__slots__ itself is). Doing so doesn't lose any information and more closely reflects the class definition body. * Allow setting __definition_order__ in type()? I don't see any reason to disallow "__definition_order__" in the namespace passed in to the 3 argument form of builtins.type(). Then dynamically created types can have a definition order (without needing to set cls.__definition_order__ afterward). * C-API for setting __definition_order__? I'd rather avoid any extra complexity in the PEP due to diving into C-API support for *creating* types with a __definition_order__. However, if it would be convenient enough and not a complex endeavor, I'm willing to accommodate that case in the PEP. At the same time, at the C-API level is it so important to accommodate __definition_order__ at class-creation time? Can't you directly modify cls.__dict__ in C? Perhaps it would be safer to have a simple C-API function to set __definition_order__ for you? * Drop the "read-only attribute" requirement? I really like that read-only implies "complete", which is a valuable message for __definition_order__ to convey. I think that there's a lot to be said for communicating about a value in that way. At the same time, most of the time Python doesn't keep you from fiddling with similar "complete" values (e.g. __name__, __slots__), so I see that point too. And since the interpreter (nor stdlib) doesn't rely on __definition_order__, it isn't much of a footgun (nor would setting __definition_order__ be much of an attractive nuisance). I suppose I'm having a hard time letting go of the attractiveness of "read-only == complete". However, given that you've been pretty clear what you think, I'm more at ease about it. :) Anyway, thoughts on the above would be helpful. I'll try to be responsive so we can wrap this up. -eric [1] https://github.com/python/peps/blob/master/pep-0520.txt
On Tue, Jun 28, 2016 at 10:30 AM, Eric Snow <ericsnowcurrently@gmail.com> wrote:
On Sun, Jun 26, 2016 at 5:55 PM, Guido van Rossum <guido@python.org> wrote:
On Fri, Jun 24, 2016 at 4:37 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
This version looks fine to me.
Same to me, mostly.
I've updated the PEP per everyone's comments [1], except I still haven't dropped the read-only __definition_order__ constraint. I'll do that when I resolve the open questions, on which I'd like some feedback:
* What about __slots__?
In addition to including __slots__ in __definition_order__, the options I see are to either ignore the names in __slots__, put them into __definition_order__ right after __slots__, or stick them in at the end (since their descriptors are added afterward). I'm leaning toward the first one, leaving the slot names out of __definition_order__ since the names aren't actually part of the definition (__slots__ itself is). Doing so doesn't lose any information and more closely reflects the class definition body.
Sounds fine. I guess this means you don't have to do anything special, right?
* Allow setting __definition_order__ in type()?
I don't see any reason to disallow "__definition_order__" in the namespace passed in to the 3 argument form of builtins.type(). Then dynamically created types can have a definition order (without needing to set cls.__definition_order__ afterward).
Right.
* C-API for setting __definition_order__?
I'd rather avoid any extra complexity in the PEP due to diving into C-API support for *creating* types with a __definition_order__. However, if it would be convenient enough and not a complex endeavor, I'm willing to accommodate that case in the PEP. At the same time, at the C-API level is it so important to accommodate __definition_order__ at class-creation time? Can't you directly modify cls.__dict__ in C? Perhaps it would be safer to have a simple C-API function to set __definition_order__ for you?
What's the use case even? I think if __definition_order__ is writable then C code can just use PyObject_SetAttrString(<class_object>, "__definition_order__", <some_tuple>).
* Drop the "read-only attribute" requirement?
I really like that read-only implies "complete", which is a valuable message for __definition_order__ to convey. I think that there's a lot to be said for communicating about a value in that way.
But it's still unique behavior, and it's not needed to protect CPython internals.
At the same time, most of the time Python doesn't keep you from fiddling with similar "complete" values (e.g. __name__, __slots__), so I see that point too. And since the interpreter (nor stdlib) doesn't rely on __definition_order__, it isn't much of a footgun (nor would setting __definition_order__ be much of an attractive nuisance).
I suppose I'm having a hard time letting go of the attractiveness of "read-only == complete". However, given that you've been pretty clear what you think, I'm more at ease about it. :)
Yeah, it's time to drop it. ;-)
Anyway, thoughts on the above would be helpful. I'll try to be responsive so we can wrap this up.
-eric
-- --Guido van Rossum (python.org/~guido)
On Tue, Jun 28, 2016 at 11:43 AM, Guido van Rossum <guido@python.org> wrote:
On Tue, Jun 28, 2016 at 10:30 AM, Eric Snow <ericsnowcurrently@gmail.com> wrote:
I suppose I'm having a hard time letting go of the attractiveness of "read-only == complete". However, given that you've been pretty clear what you think, I'm more at ease about it. :)
Yeah, it's time to drop it. ;-)
Thanks for the feedback. I've updated the PEP to resolve the open questions. Most notably, I've dropped the read-only constraint on the __definition_order__ attribute. Please let me know if you have any other outstanding concerns. Otherwise I think this PEP is ready for pronouncement. :) -eric
Awesome. That addresses my last concerns. PEP 520 is now accepted. Congratulations! On Tue, Jun 28, 2016 at 1:43 PM, Eric Snow <ericsnowcurrently@gmail.com> wrote:
On Tue, Jun 28, 2016 at 11:43 AM, Guido van Rossum <guido@python.org> wrote:
On Tue, Jun 28, 2016 at 10:30 AM, Eric Snow <ericsnowcurrently@gmail.com> wrote:
I suppose I'm having a hard time letting go of the attractiveness of "read-only == complete". However, given that you've been pretty clear what you think, I'm more at ease about it. :)
Yeah, it's time to drop it. ;-)
Thanks for the feedback. I've updated the PEP to resolve the open questions. Most notably, I've dropped the read-only constraint on the __definition_order__ attribute. Please let me know if you have any other outstanding concerns. Otherwise I think this PEP is ready for pronouncement. :)
-eric
-- --Guido van Rossum (python.org/~guido)
On Fri, Jun 24, 2016, at 17:52, Eric Snow wrote:
- 2 open questions (__slots__? drop read-only requirement?)
It's worth noting that __slots__ itself doesn't have a read-only requirement. It can be a tuple, any iterable of strings, or a single string (which means the object has a single slot). Should dir() iterate in the order of __definition_order__? What, if so, should be done about instance attributes, or attributes of multiple classes, or class attributes not present in __definition_order__? What happens to classes whose __prepare__ doesn't return an OrderedDict? Can __definition_order__ be reassigned at runtime? Will it have the same constraints? What if a metaclass defines __getattribute__ in a way that specially handles __definition_order__? If someone really wants to put a non-tuple there they will find a way. How hard do we want to think about ways to stop consenting adults from doing weird things with the __definition_order__ attribute?
On Fri, Jun 24, 2016 at 5:56 PM, Random832 <random832@fastmail.com> wrote:
On Fri, Jun 24, 2016, at 17:52, Eric Snow wrote:
- 2 open questions (__slots__? drop read-only requirement?)
It's worth noting that __slots__ itself doesn't have a read-only requirement. It can be a tuple, any iterable of strings, or a single string (which means the object has a single slot).
That is somewhat orthogonal to this PEP.
Should dir() iterate in the order of __definition_order__? What, if so, should be done about instance attributes, or attributes of multiple classes, or class attributes not present in __definition_order__?
dir() relates to the object's namespace, not its class's definition namespace.
What happens to classes whose __prepare__ doesn't return an OrderedDict?
The PEP already indicates that __definition_order__ will be set to None.
Can __definition_order__ be reassigned at runtime?
That is the subject of one of the open questions. Guido has suggested that it should. I don't agree, but then I'm not Dutch. :)
Will it have the same constraints?
Given that folks generally shouldn't be setting it at runtime, there isn't much point to constraining it. :)
What if a metaclass defines __getattribute__ in a way that specially handles __definition_order__? If someone really wants to put a non-tuple there they will find a way. How hard do we want to think about ways to stop consenting adults from doing weird things with the __definition_order__ attribute?
The point of "consenting adults" is that the person breaking the rules is aware that they are doing so and that they are willing to accept the consequences. Also, note that the interpreter does not depend on __definition_order__ in any way. As I say in the PEP, I'd rather __definition_order__ remain read-only until there's a need. -eric
Hi, On 24 June 2016 at 23:52, Eric Snow <ericsnowcurrently@gmail.com> wrote:
Pending feedback, the impact on Python implementations is expected to be minimal. If a Python implementation cannot support switching to `OrderedDict``-by-default then it can always set ``__definition_order__`` to ``None``.
That's wishful thinking. Any Python implementation that sets ``__definition_order__`` to None where CPython sets it to something useful is likely going to break programs and be deemed not fully compatible. (Note: this PEP is not a problem for PyPy.) A bientôt, Armin.
participants (6)
-
Armin Rigo -
Eric Snow -
Ethan Furman -
Guido van Rossum -
Nick Coghlan -
Random832