This issue tracker has been migrated to GitHub ,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2013年05月12日 06:51 by ncoghlan, last changed 2022年04月11日 14:57 by admin. This issue is now closed.
| Messages (12) | |||
|---|---|---|---|
| msg188981 - (view) | Author: Alyssa Coghlan (ncoghlan) * (Python committer) | Date: 2013年05月12日 06:51 | |
Creating this as a separate issue so as not to delay incorporation of the accepted PEP. One legitimate criticism of the accepted PEP 435 is that the combination of requiring explicit assignment of values *and* allowing aliasing by default is that aliases may be created inadvertently. I believe we can actually do better than the initial implementation by making the following work: >>> class Shape(Enum): ... square = 2 ... diamond = 1 ... circle = 3 ... alias_for_square = square ... >>> Shape.square <Shape.square: 2> >>> Shape.alias_for_square <Shape.square: 2> >>> Shape(2) <Shape.square: 2> While *disallowing* the following: >>> class Shape(Enum): ... square = 2 ... diamond = 1 ... circle = 3 ... alias_for_square = 2 ... How, do you ask? By wrapping non-descriptors on assignment in a placeholder type, and keeping track of which values we have already seen. If a new attribute is mapped to a placeholder, then that's fine, we accept it as an explicit declaration of an alias. However, if it's mapped directly to a repeat value, then that would be disallowed (as it was in earlier versions of the PEP). |
|||
| msg188983 - (view) | Author: Alex Gaynor (alex) * (Python committer) | Date: 2013年05月12日 06:54 | |
This would preclude code like: class Shape(Enum): rectangle = shape = 2 which seems (to me) to be the most reasonable way to express aliasing. |
|||
| msg188988 - (view) | Author: Alyssa Coghlan (ncoghlan) * (Python committer) | Date: 2013年05月12日 07:56 | |
That's a terrible way to express aliasing, because it's really unclear that "rectangle" is the canonical name. By contrast: class Shape(Enum): rectangle = 2 oblong = rectangle leaves no doubt as to which is canonical and which is the alias. You never need to go beyond two assignments, as you can still use multiple target assignment for the aliases. |
|||
| msg189008 - (view) | Author: Ethan Furman (ethan.furman) * (Python committer) | Date: 2013年05月12日 10:44 | |
Another approach to handling this, and other, issues is to allow options to EnumMeta. My original aenum code had the default Enum class as unordered, no duplicates allowed, non-indexable, etc., but then allowed options to be passed in such as DUPLICATES to allow duplicates, ORDERED to add the ge-gt-le-lt methods, INDEXED to add __index__, etc. For the aliasing issue this method is more robust as placeholders are not required, and code like this will work: class Physics(Enum): e = 2.81847 pi = 3.141596 tau = 2 * pi To make that code work with placeholders is possible (I have it in aenum) but a major pain (I was about to remove it before my offer to help with ref435 was accepted). |
|||
| msg189024 - (view) | Author: Alyssa Coghlan (ncoghlan) * (Python committer) | Date: 2013年05月12日 12:44 | |
Hmm, that's an interesting point about allowing operations on the already defined values. You could get around that by requiring that the wrapper be explicit when definined the alias: >>> class Shape(enum.Enum): ... rectangle = 1 ... oblong = enum.alias(rectangle) Or, equivalently: >>> class Shape(enum.Enum): ... rectangle = 1 ... oblong = enum.alias(1) So simple typos would trigger an error by default, and the enum.alias wrapper would tell the namespace (or the metaclass) "hey, this should be an alias for another value already defined here". I definitely don't want us to turn the metaclass into a swiss army knife of behavioural options - I'm happy with customisation hooks in the metaclass on that front, as I believe it is an effective way to discourage excessive use of metaclass magic without preventing it when it is necessary. |
|||
| msg189042 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2013年05月12日 16:12 | |
That's way too much magic for my taste. |
|||
| msg189043 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2013年05月12日 16:14 | |
Also, since we currently don't forbid the following:
>>> {'a': 1, 'a': 2}
{'a': 2}
I don't see why enums should be any different. Recommend closing.
|
|||
| msg189071 - (view) | Author: Alyssa Coghlan (ncoghlan) * (Python committer) | Date: 2013年05月12日 23:21 | |
The difference is the use case: dicts are a general purpose data store, enums are typically for defining mutually exclusive named values, with aliasing as a concession to practical reality. |
|||
| msg189074 - (view) | Author: Guido van Rossum (gvanrossum) * (Python committer) | Date: 2013年05月12日 23:41 | |
I'm with Antoine. Trying to prevent accidental redefinition behavior like Nick proposes feels like un-Pythonic coddling to me, and I expect we'd be closing off some occasionally useful patterns. Please leave well enough alone. |
|||
| msg189083 - (view) | Author: Alyssa Coghlan (ncoghlan) * (Python committer) | Date: 2013年05月13日 00:06 | |
OK, I mainly wanted to make sure this alternative was at least considered, as I didn't see it come up during the PEP discussions. |
|||
| msg189138 - (view) | Author: Barry A. Warsaw (barry) * (Python committer) | Date: 2013年05月13日 14:26 | |
On May 12, 2013, at 06:51 AM, Nick Coghlan wrote: >>>> class Shape(Enum): >... square = 2 >... diamond = 1 >... circle = 3 >... alias_for_square = square I see Guido pronounced against it, but I'm just registering that I kind of like this. You could probably have guess that since flufl.enum doesn't allow aliases at all mostly because of the potential for accidental duplicate values, which this would avoid. Hmm. LP: #1179529 |
|||
| msg189197 - (view) | Author: Alyssa Coghlan (ncoghlan) * (Python committer) | Date: 2013年05月14日 03:56 | |
I just wanted to note that there's a trivial way to prevent accidental aliases inline or in your test suite if you don't intend them: class MyEnum(Enum): .... assert len(MyEnum) == len(MyEnum.__members__) |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:57:45 | admin | set | github: 62159 |
| 2013年05月14日 03:56:24 | ncoghlan | set | messages: + msg189197 |
| 2013年05月13日 14:26:48 | barry | set | messages: + msg189138 |
| 2013年05月13日 14:21:44 | barry | set | nosy:
+ barry |
| 2013年05月13日 00:06:17 | ncoghlan | set | status: open -> closed messages: + msg189083 dependencies: - Code, test, and doc review for PEP-0435 Enum resolution: rejected stage: needs patch -> resolved |
| 2013年05月12日 23:41:46 | gvanrossum | set | messages: + msg189074 |
| 2013年05月12日 23:21:49 | ncoghlan | set | messages: + msg189071 |
| 2013年05月12日 16:14:01 | pitrou | set | messages: + msg189043 |
| 2013年05月12日 16:12:42 | pitrou | set | nosy:
+ pitrou messages: + msg189042 |
| 2013年05月12日 16:07:01 | dilettant | set | nosy:
+ dilettant |
| 2013年05月12日 15:07:24 | gvanrossum | set | nosy:
+ gvanrossum |
| 2013年05月12日 12:44:41 | ncoghlan | set | messages: + msg189024 |
| 2013年05月12日 10:44:26 | ethan.furman | set | nosy:
+ ethan.furman messages: + msg189008 |
| 2013年05月12日 10:31:49 | eric.smith | set | nosy:
+ eric.smith |
| 2013年05月12日 10:11:30 | ncoghlan | set | priority: normal -> high |
| 2013年05月12日 07:56:05 | ncoghlan | set | messages: + msg188988 |
| 2013年05月12日 06:54:08 | alex | set | nosy:
+ alex messages: + msg188983 |
| 2013年05月12日 06:51:58 | ncoghlan | set | dependencies: + Code, test, and doc review for PEP-0435 Enum |
| 2013年05月12日 06:51:37 | ncoghlan | create | |