Re: [Python-Dev] constant/enum type in stdlib
Rob Cliffe wrote: But when a frozen list a.k.a. tuple would be created - either directly, or by setting a list's mutable flag to False which would really turn it into a tuple - the size *would* be known. But at that point the object consists of two memory blocks -- one containing just the object header and a pointer to the items, and the other containing the items. To turn that into a true tuple structure would require resizing the main object block to be big enough to hold the items and copying them into it. The main object can't be moved (because there are PyObject *s all over the place pointing to it), so if there's not enough room at its current location, you're out of luck. So lists frozen after creation would have to remain as two blocks, making them second-class citizens compared to those that were created frozen. Either that or store all lists/tuples as two blocks, and give up some of the performance advantages of the current tuple structure. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
I don't see how the grouping can be completely separated from the value-naming. If the named values are to be subclassed from the base values, then you want all the members of a group to belong to the *same* subclass. You can't get that by treating each named value on its own and then trying to group them together afterwards. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 11/28/2010 09:03 PM, Ron Adam wrote: It does associate additional info to names and creates a nice dictionary to reference. def name_values( FOO: 1, BAR: Hello World!, BAZ: dict(a=1, b=2, c=3) ): ... return FOO, BAR, BAZ ... foo(1,2,3) (1, 2, 3) foo.__annotations__ {'BAR': 'Hello World!', 'FOO': 1, 'BAZ': {'a': 1, 'c': 3, 'b': 2}} sigh... I havn't been very focused lately. That should have been: def named_values(FOO:1, BAR:Hello World!, BAZ:dict(a=1, b=2, c=3)): ... return FOO, BAR, BAZ ... named_values.__annotations__ {'BAR': 'Hello World!', 'FOO': 1, 'BAZ': {'a': 1, 'c': 3, 'b': 2}} named_values(1, 2, 3) (1, 2, 3) Cheers, Ron ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, Nov 30, 2010 at 7:36 AM, Greg Ewing greg.ew...@canterbury.ac.nz wrote: I don't see how the grouping can be completely separated from the value-naming. If the named values are to be subclassed from the base values, then you want all the members of a group to belong to the *same* subclass. You can't get that by treating each named value on its own and then trying to group them together afterwards. Note that my sample implementation cached the created types, so that (for example) there was only ever one Namedint type (my implementation wasn't quite kosher in that respect, since functools.lru_cache has a non-optional size limit - setting maxsize to float('inf') deals with that). A grouping API would use either single or multiple inheritance to create members that supported both the naming aspects as well as the grouping aspects. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 28/11/2010 03:20, Terry Reedy wrote: On 11/27/2010 6:26 PM, Raymond Hettinger wrote: Can I suggest that an enum-maker be offered as a third-party module Possibly with competing versions for trial and testing ;-) rather than prematurely adding it into the standard library. I had same thought. There are already *several* enum packages for Python available. The implementation by Ben Finney, associated with the previous PEP, is on PyPI and the most recent release has over 4000 downloads making it reasonably popular: http://pypi.python.org/pypi/enum/ Other contenders include flufl.enum and lazr.enum. The Twisted guys would like a named constant type, and have a ticket for it, and PyQt has its own implementation (subclassing int) providing this functionality. In terms of assessing *general* usefulness in the wider community that step has already been done. This discussion came out of yet-another-set-of-integer-constants being added to the Python standard library (since changed to strings). We have integer constants, with the associated inscrutability when used from the interactive interpreter or debugging, in *many* standard library modules. The particular features and use cases being discussed have use *within* the standard library in mind. Releasing yet-another-enum-library-that-the-standard-library-can't-use would be a particularly pointless outcome of this discussion. The decision is whether or not to use named constants in the standard library, otherwise we can just point people at one of the several existing packages. All the best, Michael Foord -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 28/11/2010 02:38, Nick Coghlan wrote: On Sun, Nov 28, 2010 at 9:26 AM, Raymond Hettinger raymond.hettin...@gmail.com wrote: On Nov 27, 2010, at 12:56 PM, Glenn Linderman wrote: On 11/27/2010 2:51 AM, Nick Coghlan wrote: Not quite. I'm suggesting a factory function that works for any value, and derives the parent class from the type of the supplied value. Nick, thanks for the much better implementation than I achieved; you seem to have the same goals as my implementation. I learned a bit making mine, and more understanding yours to some degree. What I still don't understand about your implementation, is that when adding one additional line to your file, it fails: w = named_value(ABC, z ) Now I can understand why it might not be a good thing to make a named value of a named value (confusing, at least), but I was surprised, and still do not understand, that it failed reporting the __new__() takes exactly 3 arguments (2 given). Can I suggest that an enum-maker be offered as a third-party module rather than prematurely adding it into the standard library. Indeed. Glenn's failing example suggests to me that using a new metaclass is probably going to be a cleaner option than trying to dance around type's default behaviour within an ordinary class definition (if nothing else, a separate metaclass makes it much easier to detect when you're dealing with an instance of a named type). Yep, for representing a group of names a single class with a metaclass seems like a reasonable approach. See my note below about agreeing minimal feature-set and minimal-api before we discuss implementation though. Regardless, I still see value in approaching this whole discussion as a two-level design problem, with named values as the more fundamental concept, and then higher level grouping APIs to get enum-style behaviour. It seems like using the term enum provokes a strong negative reaction in some of the core-devs who are basically in favour named constants and not actively against grouping. I'm happy with NamedConstant and GroupedNames (or similar) and dropping the use of the term enum. There are also valid concerns about over-engineering (and not so valid concerns...). Simplicity in creating them and no additional burden in using them are fundamental, but in the APIs / implementations suggested so far I think we are keeping that in mind. Eventually attaining One Obvious Way for the former seems achievable to me, while the diversity of use cases for grouping APIs suggests to me that one-size-fits-all isn't going to work unless that one size is a Frankenstein API with more options than anyone could reasonably hope to keep in their head at once. Well... yes - treating it as a two level design problem is fine. I don't think there are *many* competing features, in fact as far as feature requests on python-dev go I think this is a relatively straightforward one with a lot of *agreement* on the basic functionality. We have had various discussions about what the API should look like, or what the implementation should look like, but I don't think there is a lot of disagreement about basic features. There are some 'optional features'. Many of these can be added later without backwards compatibility issues, so those can profitably be omitted from an initial implementation. Features as I see them: Named constant -- * Nice repr * Subclass of the type it represents * Trivially easy to convert either to a string (name) and the value it represents * If an integer type, can be OR'd with other named constants and retains a useful repr Grouped constants * Easy to create a group of named constants, accessible as attributes on group object * Capability to go from name or value to corresponding constants Optional Features --- * Ability to dynamically add new named values to a group. (Suggested by Guido) * Ability to test if a name or value is in a group * Ability to list all names in a group * ANDing as well as ORing * Constants are unique * OR'ing with an integer will look up the name (or calculate it if the int itself represents flags that have already been OR'd) and return a named value (with useful repr) instead of just an integer * Named constants be named values that can wrap *any* type and not just immutable values. (Note that wrapping mutable types makes providing from_value functionality harder *unless* we guarantee that named values are unique. If they aren't unique named values for a mutable type can have different values and there is no single definition of what the named value actually is.) Requiring that values only have one name - or alternatively that values on a group could have multiple names (obviously incompatible features). * Requiring all names in a group to be of the same type * Allow names to be set automatically in a namespace, for example in a class namespace or on a module * Allow subclassing and
Re: [Python-Dev] constant/enum type in stdlib
On 28/11/2010 16:28, Michael Foord wrote: [snip...] I don't think there are *many* competing features, in fact as far as feature requests on python-dev go I think this is a relatively straightforward one with a lot of *agreement* on the basic functionality. We have had various discussions about what the API should look like, or what the implementation should look like, but I don't think there is a lot of disagreement about basic features. There are some 'optional features'. Many of these can be added later without backwards compatibility issues, so those can profitably be omitted from an initial implementation. Features as I see them: Named constant -- * Nice repr * Subclass of the type it represents * Trivially easy to convert either to a string (name) and the value it represents * If an integer type, can be OR'd with other named constants and retains a useful repr Note that having an OR repr is meaningless *unless* the constants are intended to be flags, OR'ing should be specified. name = NamedValue('name', value, flags=True) Where flags defaults to False. Typically you will use this through the grouping API anyway - where it can either be a keyword argument (slightly annoying because the suggestion is to create the named values through keyword arguments) or we can have two group-factory functions: Group = make_constants('Group', name1=value1, name2=value2) Flags = make_flags('Flags', name1=value1, name2=value2) It is sensible if flag values are only powers of 2; we could enforce that or not... (Another one for the optional feature list.) I forgot auto-enumeration (specifying names only and having values autogenerated) from the optional feature set by the way. I think Antoine strongly disapproves of this feature because it reminds him of C enums. Mark Dickinson thinks that the flags feature could be an optional feature too. If we have ORing it makes sense to have ANDing, so I guess they belong together. I think there is value in it though. I realise that the optional feature list is now not small, and implementing all of it would create the franken-api Nick is worried about. The minimal feature list is nicely small though and provides useful functionality. All the best, Michael Grouped constants * Easy to create a group of named constants, accessible as attributes on group object * Capability to go from name or value to corresponding constants Optional Features --- * Ability to dynamically add new named values to a group. (Suggested by Guido) * Ability to test if a name or value is in a group * Ability to list all names in a group * ANDing as well as ORing * Constants are unique * OR'ing with an integer will look up the name (or calculate it if the int itself represents flags that have already been OR'd) and return a named value (with useful repr) instead of just an integer * Named constants be named values that can wrap *any* type and not just immutable values. (Note that wrapping mutable types makes providing from_value functionality harder *unless* we guarantee that named values are unique. If they aren't unique named values for a mutable type can have different values and there is no single definition of what the named value actually is.) Requiring that values only have one name - or alternatively that values on a group could have multiple names (obviously incompatible features). * Requiring all names in a group to be of the same type * Allow names to be set automatically in a namespace, for example in a class namespace or on a module * Allow subclassing and adding of new values only present in subclass I'd rather we agree a suitable (minimal) API and feature set and go to implementation from that. For wrapping mutable types I'm tempted to say YAGNI. For the standard library wrapping integers meets almost all our use-cases except for one float. (At work we have a decimal constant as it happens.) Perhaps we could require immutable types for groups but allow arbitrary values for individual named values? For the named values api: name = NamedValue('name', value) For the grouping (tentatively accepted as reasonable by Antoine): Group = make_constants('Group', name1=value1, name2=value2) name1, name2 = Group.name1, Group.name1 flag = name1 | name2 value = int(Group.name1) name = Group('name1') # alternatively: value = Group.from_name('name1') name = Group.from_value(value1) # Group(value1) could work only if values aren't strings # perhaps: name = Group(value=value1) Group.new_name = value3 # create new value on the group names = Group.all_names() # further bikeshedding on spelling of all_names required # correspondingly 'all_values' I guess, returning the constants themselves Some of the optional features couldn't later be added without backwards compatibility concerns (I think the type checking features and requiring unique values for example). We should at least
Re: [Python-Dev] constant/enum type in stdlib
On 28/11/2010 17:05, Michael Foord wrote: [snip...] It is sensible if flag values are only powers of 2; we could enforce that or not... (Another one for the optional feature list.) Another 'optional' feature I omitted was Phillip J. Eby's suggestion / requirement that named values be pickleable. Email is clunky for handling this, is there enough support (there is still some objection that is sure) to revive the PEP or create a new one? I also didn't include Nick's suggested API, which is slightly different from the one I suggested: silly = Namegroup.from_names(Silly, FOO, BAR, BAZ) silly.FOO Silly.FOO=0 int(silly.FOO) 0 silly(0) Silly.FOO=0 x = named_value(FOO, 1) y = named_value(BAR, Hello World!) z = named_value(BAZ, dict(a=1, b=2, c=3)) set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw()) Where a named value created from an integer is an int subclass, from a dict a dict subclass and so on. Michael I forgot auto-enumeration (specifying names only and having values autogenerated) from the optional feature set by the way. I think Antoine strongly disapproves of this feature because it reminds him of C enums. Mark Dickinson thinks that the flags feature could be an optional feature too. If we have ORing it makes sense to have ANDing, so I guess they belong together. I think there is value in it though. I realise that the optional feature list is now not small, and implementing all of it would create the franken-api Nick is worried about. The minimal feature list is nicely small though and provides useful functionality. All the best, Michael Grouped constants * Easy to create a group of named constants, accessible as attributes on group object * Capability to go from name or value to corresponding constants Optional Features --- * Ability to dynamically add new named values to a group. (Suggested by Guido) * Ability to test if a name or value is in a group * Ability to list all names in a group * ANDing as well as ORing * Constants are unique * OR'ing with an integer will look up the name (or calculate it if the int itself represents flags that have already been OR'd) and return a named value (with useful repr) instead of just an integer * Named constants be named values that can wrap *any* type and not just immutable values. (Note that wrapping mutable types makes providing from_value functionality harder *unless* we guarantee that named values are unique. If they aren't unique named values for a mutable type can have different values and there is no single definition of what the named value actually is.) Requiring that values only have one name - or alternatively that values on a group could have multiple names (obviously incompatible features). * Requiring all names in a group to be of the same type * Allow names to be set automatically in a namespace, for example in a class namespace or on a module * Allow subclassing and adding of new values only present in subclass I'd rather we agree a suitable (minimal) API and feature set and go to implementation from that. For wrapping mutable types I'm tempted to say YAGNI. For the standard library wrapping integers meets almost all our use-cases except for one float. (At work we have a decimal constant as it happens.) Perhaps we could require immutable types for groups but allow arbitrary values for individual named values? For the named values api: name = NamedValue('name', value) For the grouping (tentatively accepted as reasonable by Antoine): Group = make_constants('Group', name1=value1, name2=value2) name1, name2 = Group.name1, Group.name1 flag = name1 | name2 value = int(Group.name1) name = Group('name1') # alternatively: value = Group.from_name('name1') name = Group.from_value(value1) # Group(value1) could work only if values aren't strings # perhaps: name = Group(value=value1) Group.new_name = value3 # create new value on the group names = Group.all_names() # further bikeshedding on spelling of all_names required # correspondingly 'all_values' I guess, returning the constants themselves Some of the optional features couldn't later be added without backwards compatibility concerns (I think the type checking features and requiring unique values for example). We should at least consider these if we are to make adding them later difficult. I would be fine with not having these features. All the best, Michael Cheers, Nick. -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without
Re: [Python-Dev] constant/enum type in stdlib
Michael Foord wrote: Another 'optional' feature I omitted was Phillip J. Eby's suggestion / requirement that named values be pickleable. Email is clunky for handling this, is there enough support (there is still some objection that is sure) to revive the PEP or create a new one? I think it definitely needs a PEP. I don't care whether you revive the old PEP or write a new one. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 28/11/2010 18:05, Steven D'Aprano wrote: Michael Foord wrote: Another 'optional' feature I omitted was Phillip J. Eby's suggestion / requirement that named values be pickleable. Email is clunky for handling this, is there enough support (there is still some objection that is sure) to revive the PEP or create a new one? I think it definitely needs a PEP. I don't care whether you revive the old PEP or write a new one. Well, if it were to be accepted it would need a PEP and the next step should be a PEP are slightly different statements. :-) As I agree with the former *anyway* at the worst starting a PEP will waste time, so I guess I'll get that underway when I get a chance... Thanks Michael -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Rob Cliffe wrote: But couldn't they be presented to the Python programmer as a single type, with the implementation details hidden under the hood? Not in CPython, because tuple items are kept in the same block of memory as the object header. Because CPython can't move objects, this means that the size of the tuple must be known when the object is created. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Mon, Nov 29, 2010 at 2:28 AM, Michael Foord fuzzy...@voidspace.org.uk wrote: For wrapping mutable types I'm tempted to say YAGNI. For the standard library wrapping integers meets almost all our use-cases except for one float. (At work we have a decimal constant as it happens.) Perhaps we could require immutable types for groups but allow arbitrary values for individual named values? Whereas my opinion is that immutable vs mutable is such a blurry distinction that we shouldn't try to make it at the lowest level. Would it be possible to name frozenset instances? Tuples? How about objects that are conceptually immutable, but don't close all the loopholes allowing you to mutate them? (e.g. Decimal, Fraction) Better to design a named value API that doesn't care about mutability, and then leave questions of reverse mappings from values back to names to the grouping API level. At that level, it would be trivial (and natural) to limit names to referencing Hashable values so that a reverse lookup table would be easy to implement. For standard library purposes, we could even reasonably provide an int-only grouping API, since the main use case is almost certainly to be in managing translation of OS-level integer constants to named values. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 29/11/2010 00:48, Nick Coghlan wrote: On Mon, Nov 29, 2010 at 2:28 AM, Michael Foord fuzzy...@voidspace.org.uk wrote: For wrapping mutable types I'm tempted to say YAGNI. For the standard library wrapping integers meets almost all our use-cases except for one float. (At work we have a decimal constant as it happens.) Perhaps we could require immutable types for groups but allow arbitrary values for individual named values? Whereas my opinion is that immutable vs mutable is such a blurry distinction that we shouldn't try to make it at the lowest level. Would it be possible to name frozenset instances? Tuples? How about objects that are conceptually immutable, but don't close all the loopholes allowing you to mutate them? (e.g. Decimal, Fraction) Better to design a named value API that doesn't care about mutability, and then leave questions of reverse mappings from values back to names to the grouping API level. At that level, it would be trivial (and natural) to limit names to referencing Hashable values so that a reverse lookup table would be easy to implement. For standard library purposes, we could even reasonably provide an int-only grouping API, since the main use case is almost certainly to be in managing translation of OS-level integer constants to named values. Sounds reasonable to me. Michael Cheers, Nick. -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 28/11/2010 21:23, Greg Ewing wrote: Rob Cliffe wrote: But couldn't they be presented to the Python programmer as a single type, with the implementation details hidden under the hood? Not in CPython, because tuple items are kept in the same block of memory as the object header. Because CPython can't move objects, this means that the size of the tuple must be known when the object is created. But when a frozen list a.k.a. tuple would be created - either directly, or by setting a list's mutable flag to False which would really turn it into a tuple - the size *would* be known. And since the object would now be immutable, there would be no requirement for its size to change. (My idea doesn't require additional functionality, just a different API.) Rob Cliffe ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 11/27/2010 04:51 AM, Nick Coghlan wrote: x = named_value(FOO, 1) y = named_value(BAR, Hello World!) z = named_value(BAZ, dict(a=1, b=2, c=3)) print(x, y, z, sep=\n) print(\n.join(map(repr, (x, y, z print(\n.join(map(str, map(type, (x, y, z) set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw()) print(\n.join(map(repr, (foo, bar, baz print(type(x) is type(foo), type(y) is type(bar), type(z) is type(baz)) == # Session output for the last 6 lines print(x, y, z, sep=\n) 1 Hello World! {'a': 1, 'c': 3, 'b': 2} print(\n.join(map(repr, (x, y, z FOO=1 BAR='Hello World!' BAZ={'a': 1, 'c': 3, 'b': 2} This reminds me of python annotations. Which seem like an already forgotten new feature. Maybe they can help with this? It does associate additional info to names and creates a nice dictionary to reference. def name_values( FOO: 1, BAR: Hello World!, BAZ: dict(a=1, b=2, c=3) ): ... return FOO, BAR, BAZ ... foo(1,2,3) (1, 2, 3) foo.__annotations__ {'BAR': 'Hello World!', 'FOO': 1, 'BAZ': {'a': 1, 'c': 3, 'b': 2}} Cheers, Ron ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Thu, Nov 25, 2010 at 3:41 AM, Michael Foord fuzzy...@voidspace.org.uk wrote: Can you explain what you see as the difference? I'm not particularly interested in type validation but I like the fact that typical enum APIs allow you to group constants: the generated constant class acts as a namespace for all the defined constants. The problem with blessing one particular enum API is that people have so many different ideas as to what an enum API should look like. However, the one thing they all have in common is the ability to take a value and give it a name, then present *both* of those in debugging information. Are you just suggesting something along the lines of: class NamedConstant(int): def __new__(cls, name, val): return int.__new__(cls, val) def __init__(self, name, val): self._name = name def __repr__(self): return 'NamedConstant %s' % self._name FOO = NamedConstant('FOO', 3) In general the less features the better, but I'd like a few more features than that. :-) Not quite. I'm suggesting a factory function that works for any value, and derives the parent class from the type of the supplied value. However, what you wrote is still the essence of the idea - we would be primarily providing a building block that makes it easier for people to *create* enum APIs if they want to, but for simple use cases (where all they really wanted was the enhanced debugging information) they wouldn't need to bother. In the standard library, wherever we do enum-like things we would switch to using named values where it makes sense to do so. Doing so may actually make sense for more than just constants - it may make sense for significant mutable globals as well. == # Implementation (more than just a sketch, since it handles some interesting corner cases) import functools @functools.lru_cache() def _make_named_value_type(base_type): class _NamedValueType(base_type): def __new__(cls, name, value): return base_type.__new__(cls, value) def __init__(self, name, value): self.__name = name super().__init__(value) @property def _name(self): return self.__name def _raw(self): return base_type(self) def __repr__(self): return {}={}.format(self._name, super().__repr__()) if base_type.__str__ is object.__str__: __str__ = base_type.__repr__ _NamedValueType.__name__ = Named{}.format(base_type.__name__) return _NamedValueType def named_value(name, value): return _make_named_value_type(type(value))(name, value) def set_named_values(namespace, **kwds): for k, v in kwds.items(): namespace[k] = named_value(k, v) x = named_value(FOO, 1) y = named_value(BAR, Hello World!) z = named_value(BAZ, dict(a=1, b=2, c=3)) print(x, y, z, sep=\n) print(\n.join(map(repr, (x, y, z print(\n.join(map(str, map(type, (x, y, z) set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw()) print(\n.join(map(repr, (foo, bar, baz print(type(x) is type(foo), type(y) is type(bar), type(z) is type(baz)) == # Session output for the last 6 lines print(x, y, z, sep=\n) 1 Hello World! {'a': 1, 'c': 3, 'b': 2} print(\n.join(map(repr, (x, y, z FOO=1 BAR='Hello World!' BAZ={'a': 1, 'c': 3, 'b': 2} print(\n.join(map(str, map(type, (x, y, z) class '__main__.Namedint' class '__main__.Namedstr' class '__main__.Nameddict' set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw()) print(\n.join(map(repr, (foo, bar, baz foo=1 bar='Hello World!' baz={'a': 1, 'c': 3, 'b': 2} print(type(x) is type(foo), type(y) is type(bar), type(z) is type(baz)) True True True For normal use, such objects would look like ordinary instances of their class. They would only behave differently when their representation is printed (prepending their name), or when their type is interrogated (being an instance of the named subclass rather than the ordinary type). Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 27/11/2010 10:51, Nick Coghlan wrote: On Thu, Nov 25, 2010 at 3:41 AM, Michael Foord fuzzy...@voidspace.org.uk wrote: Can you explain what you see as the difference? I'm not particularly interested in type validation but I like the fact that typical enum APIs allow you to group constants: the generated constant class acts as a namespace for all the defined constants. The problem with blessing one particular enum API is that people have so many different ideas as to what an enum API should look like. There actually seemed to be quite a bit of agreement around basic functionality though. However, the one thing they all have in common is the ability to take a value and give it a name, then present *both* of those in debugging information. And this is the most important functionality. I would say that the grouping (namespacing) of constants is also useful, provided by *most* Python enum APIs and easy to implement without over complexifying the API. (Note that there is no *particular* hurry to get this into 3.2 - the beta is due imminently. I wouldn't object to it ) Are you just suggesting something along the lines of: class NamedConstant(int): def __new__(cls, name, val): return int.__new__(cls, val) def __init__(self, name, val): self._name = name def __repr__(self): return 'NamedConstant %s' % self._name FOO = NamedConstant('FOO', 3) In general the less features the better, but I'd like a few more features than that. :-) Not quite. I'm suggesting a factory function that works for any value, and derives the parent class from the type of the supplied value. However, what you wrote is still the essence of the idea - we would be primarily providing a building block that makes it easier for people to *create* enum APIs if they want to, but for simple use cases (where all they really wanted was the enhanced debugging information) they wouldn't need to bother. In the standard library, wherever we do enum-like things we would switch to using named values where it makes sense to do so. Doing so may actually make sense for more than just constants - it may make sense for significant mutable globals as well. Very interesting proposal (typed named values rather than just named constants). It doesn't handle flag values, which I would still like, but that only really makes sense for integers (sets can be OR'd but their representation is already understandable). Perhaps the integer named type could be special cased for that. Without the grouping functionality (associating a bunch of names together) you lose the 'from_name' functionality. Guido was in favour of this, and it is an obvious feature where you have grouping: http://mail.python.org/pipermail/python-dev/2010-November/105912.html I expect that the API to convert between enums and bare ints should be i = int(e) and e = enumclass(i). It would be nice if s = str(e) and e = enumclass(s) would work too. This wouldn't work with your suggested implementation (as it is). Grouping and mutable named values could be inefficient and have issues around identity / equality. Maybe restrict the API to the immutable primitives. All the best, Michael == # Implementation (more than just a sketch, since it handles some interesting corner cases) import functools @functools.lru_cache() def _make_named_value_type(base_type): class _NamedValueType(base_type): def __new__(cls, name, value): return base_type.__new__(cls, value) def __init__(self, name, value): self.__name = name super().__init__(value) @property def _name(self): return self.__name def _raw(self): return base_type(self) def __repr__(self): return {}={}.format(self._name, super().__repr__()) if base_type.__str__ is object.__str__: __str__ = base_type.__repr__ _NamedValueType.__name__ = Named{}.format(base_type.__name__) return _NamedValueType def named_value(name, value): return _make_named_value_type(type(value))(name, value) def set_named_values(namespace, **kwds): for k, v in kwds.items(): namespace[k] = named_value(k, v) x = named_value(FOO, 1) y = named_value(BAR, Hello World!) z = named_value(BAZ, dict(a=1, b=2, c=3)) print(x, y, z, sep=\n) print(\n.join(map(repr, (x, y, z print(\n.join(map(str, map(type, (x, y, z) set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw()) print(\n.join(map(repr, (foo, bar, baz print(type(x) is type(foo), type(y) is type(bar), type(z) is type(baz)) == # Session output for the last 6 lines print(x, y, z, sep=\n) 1 Hello World! {'a': 1, 'c': 3, 'b': 2} print(\n.join(map(repr, (x, y, z FOO=1 BAR='Hello World!' BAZ={'a': 1, 'c': 3, 'b': 2} print(\n.join(map(str,
Re: [Python-Dev] constant/enum type in stdlib
On Sun, Nov 28, 2010 at 12:01 AM, Michael Foord fuzzy...@voidspace.org.uk wrote: Very interesting proposal (typed named values rather than just named constants). It doesn't handle flag values, which I would still like, but that only really makes sense for integers (sets can be OR'd but their representation is already understandable). Perhaps the integer named type could be special cased for that. Without the grouping functionality (associating a bunch of names together) you lose the 'from_name' functionality. Guido was in favour of this, and it is an obvious feature where you have grouping: http://mail.python.org/pipermail/python-dev/2010-November/105912.html I expect that the API to convert between enums and bare ints should be i = int(e) and e = enumclass(i). It would be nice if s = str(e) and e = enumclass(s) would work too. Note that the i = int(e) and s = str(e) parts of Guido's expectation do work (they are, in fact, the underling implementation of the _raw() method), so an enum class would only be needed to provide the other half of the equation. The named values have no opinion on equivalence at all (they just defer to the parent class), but change the rules for identity (which are always murky anyway, since caching is optional even for immutable types). This wouldn't work with your suggested implementation (as it is). Grouping and mutable named values could be inefficient and have issues around identity / equality. Maybe restrict the API to the immutable primitives. My proposal doesn't say anything about grouping at all - it's just an idea for here's a standard way to associate a canonical name with a particular object, independent of the namespaces that happen to reference that object. Now, a particular *grouping* API may want to restrict itself in various ways, but that's my point. We should be looking at a standard solution for the ground level problem (i.e. the idea named_value attempts to solve) and then let various 3rd party enum/name grouping implementations flourish on top of that, rather than trying to create an all-singing all-dancing value grouping API (which is going to be far more intrusive than a simple API for here's a way to give your constants and important data structures names that show up in their representations). For example, using named_value as a primitive, you can fairly easily do: class Namegroup: # Missing lots of niceties of a real enum class, but shows the idea # as to how a real implementation could leverage named_value def __init__(self, _groupname, **kwds): self._groupname = _groupname pattern = _groupname + .{} self._value_map = {} for k, v in kwds.items(): attr = named_value(pattern.format(k), v) setattr(self, k, attr) self._value_map[v] = attr @classmethod def from_names(cls, groupname, *args): kwds = dict(zip(args, range(len(args return cls(groupname, **kwds) def __call__(self, arg): return self._value_map[arg] silly = Namegroup.from_names(Silly, FOO, BAR, BAZ) silly.FOO Silly.FOO=0 int(silly.FOO) 0 silly(0) Silly.FOO=0 named_value deals with all the stuff to do with pretending to be the original type of object (only with an associated name), leaving the grouping API to deal with issues of creating groups of names and mapping between them and the original values in various ways. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Nov 27, 2010, at 02:01 PM, Michael Foord wrote: (Note that there is no *particular* hurry to get this into 3.2 - the beta is due imminently. I wouldn't object to it ) Indeed. I don't think the time is right to try to get this into 3.2. -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 11/27/2010 2:51 AM, Nick Coghlan wrote: Not quite. I'm suggesting a factory function that works for any value, and derives the parent class from the type of the supplied value. Nick, thanks for the much better implementation than I achieved; you seem to have the same goals as my implementation. I learned a bit making mine, and more understanding yours to some degree. What I still don't understand about your implementation, is that when adding one additional line to your file, it fails: w = named_value(ABC, z ) Now I can understand why it might not be a good thing to make a named value of a named value (confusing, at least), but I was surprised, and still do not understand, that it failed reporting the __new__() takes exactly 3 arguments (2 given). ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Nov 27, 2010, at 12:56 PM, Glenn Linderman wrote: On 11/27/2010 2:51 AM, Nick Coghlan wrote: Not quite. I'm suggesting a factory function that works for any value, and derives the parent class from the type of the supplied value. Nick, thanks for the much better implementation than I achieved; you seem to have the same goals as my implementation. I learned a bit making mine, and more understanding yours to some degree. What I still don't understand about your implementation, is that when adding one additional line to your file, it fails: w = named_value(ABC, z ) Now I can understand why it might not be a good thing to make a named value of a named value (confusing, at least), but I was surprised, and still do not understand, that it failed reporting the __new__() takes exactly 3 arguments (2 given). Can I suggest that an enum-maker be offered as a third-party module rather than prematurely adding it into the standard library. Raymond ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 11/27/2010 12:56 PM, Glenn Linderman wrote: On 11/27/2010 2:51 AM, Nick Coghlan wrote: Not quite. I'm suggesting a factory function that works for any value, and derives the parent class from the type of the supplied value. Nick, thanks for the much better implementation than I achieved; you seem to have the same goals as my implementation. I learned a bit making mine, and more understanding yours to some degree. What I still don't understand about your implementation, is that when adding one additional line to your file, it fails: w = named_value(ABC, z ) Now I can understand why it might not be a good thing to make a named value of a named value (confusing, at least), but I was surprised, and still do not understand, that it failed reporting the __new__() takes exactly 3 arguments (2 given). OK, I puzzled out the error, and here is a cure of sorts. def __new__(cls, name, value): try: return base_type.__new__(cls, value) except TypeError: return base_type.__new__(cls, name, value) def __init__(self, name, value): self.__name = name try: super().__init__(value) except TypeError: super().__init__(name, value) Probably it would be better for the except clause to raise a different type of error ( Can't recursively create named value ) or to cleverly bypass the intermediate named value, and simply apply a new name to the original value. Hmm... For this, only __new__ need be changed: def __new__(cls, name, value): try: return base_type.__new__(cls, value) except TypeError: return _make_named_value_type( type( value._raw() ))( name, value._raw() ) def __init__(self, name, value): self.__name = name super().__init__(value) Thanks for not responding too quickly, I figured out more, and learned more. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Sun, Nov 28, 2010 at 9:26 AM, Raymond Hettinger raymond.hettin...@gmail.com wrote: On Nov 27, 2010, at 12:56 PM, Glenn Linderman wrote: On 11/27/2010 2:51 AM, Nick Coghlan wrote: Not quite. I'm suggesting a factory function that works for any value, and derives the parent class from the type of the supplied value. Nick, thanks for the much better implementation than I achieved; you seem to have the same goals as my implementation. I learned a bit making mine, and more understanding yours to some degree. What I still don't understand about your implementation, is that when adding one additional line to your file, it fails: w = named_value(ABC, z ) Now I can understand why it might not be a good thing to make a named value of a named value (confusing, at least), but I was surprised, and still do not understand, that it failed reporting the __new__() takes exactly 3 arguments (2 given). Can I suggest that an enum-maker be offered as a third-party module rather than prematurely adding it into the standard library. Indeed. Glenn's failing example suggests to me that using a new metaclass is probably going to be a cleaner option than trying to dance around type's default behaviour within an ordinary class definition (if nothing else, a separate metaclass makes it much easier to detect when you're dealing with an instance of a named type). Regardless, I still see value in approaching this whole discussion as a two-level design problem, with named values as the more fundamental concept, and then higher level grouping APIs to get enum-style behaviour. Eventually attaining One Obvious Way for the former seems achievable to me, while the diversity of use cases for grouping APIs suggests to me that one-size-fits-all isn't going to work unless that one size is a Frankenstein API with more options than anyone could reasonably hope to keep in their head at once. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 11/27/2010 6:26 PM, Raymond Hettinger wrote: Can I suggest that an enum-maker be offered as a third-party module Possibly with competing versions for trial and testing ;-) rather than prematurely adding it into the standard library. I had same thought. -- Terry Jan Reedy ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
So the following code defines constants with associated names that get put in the repr. I'm still a Python newbie in some areas, particularly classes and metaclasses, maybe more. But this Python 3 code seems to create constants with names ... works for int and str at least. Special case for int defines a special __or__ operator to OR both the values and the names, which some might like. Dunno why it doesn't work for dict, and it is too late to research that today. That's the last test case in the code below, so you can see how it works for int and string before it bombs. There's some obvious cleanup work to be done, and it would be nice to make the names actually be constant... but they do lose their .name if you ignorantly assign the base type, so at least it is hard to change the value and keep the associated .name that gets reported by repr, which might reduce some confusion at debug time. An idea I had, but have no idea how to implement, is that it might be nice to say: with imported_constants_from_module: do_stuff where do_stuff could reference the constants without qualifying them by module. Of course, if you knew it was just a module of constants, you could import * from module :) But the idea of with is that they'd go away at the end of that scope. Some techniques here came from Raymond's namedtuple code. def constant( name, val ): typ = str( type( val )) if typ.startswith(class ') and typ[ -2: ] == ': typ = typ[ 8:-2 ] ev = ''' class constant_%s( %s ): def __new__( cls, val, name ): self = %s.__new__( cls, val ) self.name = name return self def __repr__( self ): return self.name + ': ' + str( self ) ''' if typ == 'int': ev += ''' def __or__( self, other ): if isinstance( other, constant_int ): return constant_int( int( self ) | int( other ), self.name + ' | ' + other.name ) ''' ev += ''' %s = constant_%s( %s, '%s' ) ''' ev = ev % ( typ, typ, typ, name, typ, repr( val ), name ) print( ev ) exec( ev, globals()) constant('O_RANDOM', val=16 ) constant('O_SEQUENTIAL', val=32 ) constant(O_STRING, val=string) def foo( x ): print( str( x )) print( repr( x )) print( type( x )) foo( O_RANDOM ) foo( O_SEQUENTIAL ) foo( O_STRING ) zz = O_RANDOM | O_SEQUENTIAL foo( zz ) y = {'ab': 2, 'yz': 3 } constant('O_DICT', y ) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Thu, Nov 25, 2010 at 11:34 AM, Glenn Linderman v+pyt...@g.nevcal.com wrote: So the following code defines constants with associated names that get put in the repr. The code you gave doesn't work if the constant() function is moved into a separate module from the code that calls it. The globals() function, as I understand it, gives you access to the global namespace *of the current module*, so the constants end up being defined in the module containing constant(), not the module you're calling it from. You could get around this by passing the globals of the calling module to constant(), but I think it's cleaner to use a class to provide a distinct namespace for the constants. An idea I had, but have no idea how to implement, is that it might be nice to say: with imported_constants_from_module: do_stuff where do_stuff could reference the constants without qualifying them by module. Of course, if you knew it was just a module of constants, you could import * from module :) But the idea of with is that they'd go away at the end of that scope. I don't think this is possible - the context manager protocol doesn't allow you to modify the namespace of the caller like that. Also, a with statement does not have its own namespace; any names defined inside its body will continue to be visible in the containing scope. Of course, if you want to achieve something similar (at function scope), you could say: def foo(bar, baz): from module import * ... ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 25/11/2010 10:12, Nadeem Vawda wrote: On Thu, Nov 25, 2010 at 11:34 AM, Glenn Lindermanv+pyt...@g.nevcal.com wrote: So the following code defines constants with associated names that get put in the repr. The code you gave doesn't work if the constant() function is moved into a separate module from the code that calls it. The globals() function, as I understand it, gives you access to the global namespace *of the current module*, so the constants end up being defined in the module containing constant(), not the module you're calling it from. You could get around this by passing the globals of the calling module to constant(), but I think it's cleaner to use a class to provide a distinct namespace for the constants. An idea I had, but have no idea how to implement, is that it might be nice to say: with imported_constants_from_module: do_stuff where do_stuff could reference the constants without qualifying them by module. Of course, if you knew it was just a module of constants, you could import * from module :) But the idea of with is that they'd go away at the end of that scope. I don't think this is possible - the context manager protocol doesn't allow you to modify the namespace of the caller like that. Also, a with statement does not have its own namespace; any names defined inside its body will continue to be visible in the containing scope. Of course, if you want to achieve something similar (at function scope), you could say: def foo(bar, baz): from module import * ... Not in Python 3 you can't. :-) That's invalid syntax, import * can only be used at module level. This makes *testing* import * (i.e. testing your __all__) annoying - you have to exec('from module import *') instead. Michael ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 25/11/2010 09:34, Glenn Linderman wrote: So the following code defines constants with associated names that get put in the repr. I'm still a Python newbie in some areas, particularly classes and metaclasses, maybe more. But this Python 3 code seems to create constants with names ... works for int and str at least. Special case for int defines a special __or__ operator to OR both the values and the names, which some might like. Dunno why it doesn't work for dict, and it is too late to research that today. That's the last test case in the code below, so you can see how it works for int and string before it bombs. There's some obvious cleanup work to be done, and it would be nice to make the names actually be constant... but they do lose their .name if you ignorantly assign the base type, so at least it is hard to change the value and keep the associated .name that gets reported by repr, which might reduce some confusion at debug time. An idea I had, but have no idea how to implement, is that it might be nice to say: with imported_constants_from_module: do_stuff where do_stuff could reference the constants without qualifying them by module. Of course, if you knew it was just a module of constants, you could import * from module :) But the idea of with is that they'd go away at the end of that scope. Some techniques here came from Raymond's namedtuple code. def constant( name, val ): typ = str( type( val )) if typ.startswith(class ') and typ[ -2: ] == ': typ = typ[ 8:-2 ] ev = ''' class constant_%s( %s ): def __new__( cls, val, name ): self = %s.__new__( cls, val ) self.name = name return self def __repr__( self ): return self.name + ': ' + str( self ) ''' if typ == 'int': ev += ''' def __or__( self, other ): if isinstance( other, constant_int ): return constant_int( int( self ) | int( other ), self.name + ' | ' + other.name ) ''' Not quite correct. If you or a value you with itself you should get back just the value not something with name|name as the repr. We can hold off on implementations until we have general agreement that some kind of named constant *should* be added, and what the feature set should look like. All the best, Michael ev += ''' %s = constant_%s( %s, '%s' ) ''' ev = ev % ( typ, typ, typ, name, typ, repr( val ), name ) print( ev ) exec( ev, globals()) constant('O_RANDOM', val=16 ) constant('O_SEQUENTIAL', val=32 ) constant(O_STRING, val=string) def foo( x ): print( str( x )) print( repr( x )) print( type( x )) foo( O_RANDOM ) foo( O_SEQUENTIAL ) foo( O_STRING ) zz = O_RANDOM | O_SEQUENTIAL foo( zz ) y = {'ab': 2, 'yz': 3 } constant('O_DICT', y ) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (BOGUS AGREEMENTS) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 25/11/2010 03:46, Greg Ewing wrote: On 25/11/10 12:38, average wrote: Is immutability a general need that should have general solution? Yes, I have sometimes thought this. Might be nice to have a mutable attribute that could be read and could be changed from True to False, though presumably not vice versa. I don't think it really generalizes. Tuples are not just frozen lists, for example -- they have a different internal structure that's more efficient to create and access. But couldn't they be presented to the Python programmer as a single type, with the implementation details hidden under the hood? So MyList.__mutable__ = False would have the same effect as the present MyList = tuple(MyList) This would simplify some code that copes with either list(s) or tuple(s) as input data. One would need syntax for (im)mutable literals, e.g. []i# immutable list (really a tuple). Bit of a shame that i[] doesn't work. or []f# frozen list (same thing) [] # mutable list (same as now) []m # alternative syntax for mutable list This would reduce the overloading on parentheses and avoid having to write a tuple of one item as (t,) which often trips up newbies. It woud also avoid one FAQ: Why does Python have separate list and tuple types? Also the syntax could be extended, e.g. {a,b,c}f # frozen set with 3 objects {p:x,q:y}f # frozen dictionary with 2 items {:}f, {}f # (re the thread on set literals) frozen empty dictionary and frozen empty set! Just some thoughts for Python 4. Best wishes Rob Cliffe ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 23/11/2010 14:16, Nick Coghlan wrote: On Tue, Nov 23, 2010 at 11:50 PM, Michael Foord fuzzy...@voidspace.org.uk wrote: PEP 354 was rejected for two primary reasons - lack of interest and nowhere obvious to put it. Would it be *so bad* if an enum type lived in its own module? There is certainly more interest now, and if we are to use something like this in the standard library it *has* to be in the standard library (unless every module implements their own private _Constant class). Time to revisit the PEP? If you (or anyone else) wanted to revisit the PEP, then I would advise trawling through the standard library looking for constants that could be sensibly converted to enum values. Based on a non-exhaustive search, Python standard library modules currently using integers for constants: * re - has flags (OR'able constants) defined in sre_constants, each flag has two names (e.g. re.IGNORECASE and re.I) * os has SEEK_SET, SEEK_CUR, SEEK_END - *plus* those implemented in posix / nt * doctest has its own flag system, but is really just using integer flags / constants (quite a few of them) * token has a tonne of constants (autogenerated) * socket exports a bunch of constants defined in _socket * gzip has flags: FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT * errno (builtin module) EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED * opcode has HAVE_ARGUMENT, EXTENDED_ARG. In fact pretty much the whole of opcode is about defining and exposing named constants * msilib uses flag constants * multiprocessing.pool - RUN, CLOSE, TERMINATE * multiprocessing.util - NOTSET, SUBDEBUG, DEBUG, INFO, SUBWARNING * xml.dom and xml.dom.Node (in __init__.py) have a bunch of constants * xml.dom.NodeFilter.NodeFilter holds a bunch of constants (some of them flags) * xmlrpc.client has a bunch of error constants * calendar uses constants to represent weekdays, plus one for the EPOCH that is best left alone * http.client has a tonne of constants - recognisable as ports / error codes though * dis has flags in COMPILER_FLAG_NAMES, which are then set as locals in inspect * io defines SEEK_SET, SEEK_CUR, SEEK_END (same as os) Where constants are implemented in C but exported via a Python module (the constants exported by os and socket for example) they could be wrapped. Where they are exported directly by a C extension or builtin module (e.g. errno) they are probably best left. Raymond feels that having an enum / constant type would be Javaesque and unused. If we used it in the standard library the unused fear at least would be unwarranted. The change would be largely transparent to developers, except they get better debugging info. Twisted is also looking for an enum / constant type: http://twistedmatrix.com/trac/ticket/4671 Because we would need to subclass from int for backwards compatibility we can't (unless the base class is set dynamically which I don't propose) it couldn't replace float / string constants. Hopefully it would still be sufficient to allow Twisted to use it. (Although they do so love reimplementing parts of the standard library - usually better than the standard library it has to be said.) All the best, Michael There are a tonne of constants that are used as numbers (MAX_LINE_LENGTH appears in a few places) and aren't just arbitrary constants. There are also some other interesting ones: * pty has STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CHILD * poplib has POP3_PORT, POP3_SSL_PORT - recognisable as port numbers, should be left as ints * datetime.py has MINYEAR and MAXYEAR * colorsys has float constants * tty uses constants for termios list indexes (used as numbers I guess) * curses.ascii has a whole bunch of integer constants referring to ascii characters * Several modules - decimal, concurrent.futures, uuid (and now inspect) already use strings A decision would also need to be made as to whether or not to subclass int, or just provide __index__ (the former has the advantage of being able to drop cleanly into OS level APIs that expect a numerical constant). Whether enums should provide arbitrary name-value mappings (ala C enums) or were restricted to sequential indices starting from zero would be another question best addressed by a code survey of at least the stdlib. And getgeneratorstate() doesn't count as a use case, since the ordering isn't needed and using string literals instead of integers will cover the debugging aspect :) Cheers, Nick. -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents
Re: [Python-Dev] constant/enum type in stdlib
On Wed, Nov 24, 2010 at 10:30 PM, Michael Foord fuzzy...@voidspace.org.uk wrote: Based on a non-exhaustive search, Python standard library modules currently using integers for constants: Thanks for that review. I think following up on the NamedConstant idea may make more sense than pursuing enums in their own right. That way we could get the debugging benefits on the Python side regardless of any type constraints on the value (e.g. needing to be an integer in order to interface to C code), without needing to design an enum API that suited all purposes. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Nick Coghlan wrote: On Wed, Nov 24, 2010 at 10:30 PM, Michael Foord fuzzy...@voidspace.org.uk wrote: Based on a non-exhaustive search, Python standard library modules currently using integers for constants: Thanks for that review. I think following up on the NamedConstant idea may make more sense than pursuing enums in their own right. Pardon me if I've missed something in this thread, but when you say NamedConstant, do you mean actual constants that can only be bound once but not re-bound? If so, +1. If not, what do you mean? I thought PEP 3115 could be used to implement such constants, but I can't get it to work... class readonlydict(dict): def __setitem__(self, key, value): if key in self: raise TypeError(can't rebind constant) dict.__setitem__(self, key, value) # Need to also handle updates, del, pop, etc. class MetaConstant(type): @classmethod def __prepare__(metacls, name, bases): return readonlydict() def __new__(cls, name, bases, classdict): assert type(classdict) is readonlydict return type.__new__(cls, name, bases, classdict) class Constant(metaclass=MetaConstant): a = 1 b = 2 c = 3 What I expect is that Constant.a should return 1, and Constant.a=2 should raise TypeError, but what I get is a normal class __dict__. Constant.a 1 Constant.a = 2 Constant.a 2 -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
2010/11/24 Steven D'Aprano st...@pearwood.info: Nick Coghlan wrote: On Wed, Nov 24, 2010 at 10:30 PM, Michael Foord fuzzy...@voidspace.org.uk wrote: Based on a non-exhaustive search, Python standard library modules currently using integers for constants: Thanks for that review. I think following up on the NamedConstant idea may make more sense than pursuing enums in their own right. Pardon me if I've missed something in this thread, but when you say NamedConstant, do you mean actual constants that can only be bound once but not re-bound? If so, +1. If not, what do you mean? I thought PEP 3115 could be used to implement such constants, but I can't get it to work... class readonlydict(dict): def __setitem__(self, key, value): if key in self: raise TypeError(can't rebind constant) dict.__setitem__(self, key, value) # Need to also handle updates, del, pop, etc. class MetaConstant(type): �...@classmethod def __prepare__(metacls, name, bases): return readonlydict() def __new__(cls, name, bases, classdict): assert type(classdict) is readonlydict return type.__new__(cls, name, bases, classdict) class Constant(metaclass=MetaConstant): a = 1 b = 2 c = 3 What I expect is that Constant.a should return 1, and Constant.a=2 should raise TypeError, but what I get is a normal class __dict__. The construction namespace can be customized, but class.__dict__ must always be a real dict. -- Regards, Benjamin ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 24/11/2010 14:08, Nick Coghlan wrote: On Wed, Nov 24, 2010 at 10:30 PM, Michael Foord fuzzy...@voidspace.org.uk wrote: Based on a non-exhaustive search, Python standard library modules currently using integers for constants: Thanks for that review. I think following up on the NamedConstant idea may make more sense than pursuing enums in their own right. That way we could get the debugging benefits on the Python side regardless of any type constraints on the value (e.g. needing to be an integer in order to interface to C code), without needing to design an enum API that suited all purposes. Can you explain what you see as the difference? I'm not particularly interested in type validation but I like the fact that typical enum APIs allow you to group constants: the generated constant class acts as a namespace for all the defined constants. Are you just suggesting something along the lines of: class NamedConstant(int): def __new__(cls, name, val): return int.__new__(cls, val) def __init__(self, name, val): self._name = name def __repr__(self): return 'NamedConstant %s' % self._name FOO = NamedConstant('FOO', 3) In general the less features the better, but I'd like a few more features than that. :-) All the best, Michael Cheers, Nick. -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Is immutability a general need that should have general solution? By generalizing the idea to lists/tuples, set/frozenset, dicts, and strings (for example), it seems one could simplify the container classes, eliminate code complexity, and perhaps improve resource utilization. mark ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 25/11/10 12:38, average wrote: Is immutability a general need that should have general solution? I don't think it really generalizes. Tuples are not just frozen lists, for example -- they have a different internal structure that's more efficient to create and access. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 23/11/2010 13:41, Nick Coghlan wrote: On Tue, Nov 23, 2010 at 2:46 AM,exar...@twistedmatrix.com wrote: On 04:24 pm, solip...@pitrou.net wrote: On Mon, 22 Nov 2010 17:08:36 +0100 Hrvoje Niksichrvoje.nik...@avl.com wrote: On 11/22/2010 04:37 PM, Antoine Pitrou wrote: +1. The problem with int constants is that the int gets printed, not the name, when you dump them for debugging purposes :) Well, it's trivial to subclass int to something with a nicer __repr__. PyGTK uses that technique for wrapping C enums: Nice. It might be useful to add a private _Constant class somewhere for stdlib purposes. http://www.python.org/dev/peps/pep-0354/ Indeed, it is difficult to do enums is such a way that they feel sufficiently robust to be worth the effort of including them (although these days, I would be inclined to follow the namedtuple API style rather than that presented in PEP 354). Right. As it happens I just submitted a patch to Barry Warsaw's enum package (nice), flufl.enum [1], to allow namedtuple style creation of named constants: from flufl.enum import make_enum Colors = make_enum('Colors', 'red green blue') Colors Colors {red: 1, green: 2, blue: 3} PEP 354 was rejected for two primary reasons - lack of interest and nowhere obvious to put it. Would it be *so bad* if an enum type lived in its own module? There is certainly more interest now, and if we are to use something like this in the standard library it *has* to be in the standard library (unless every module implements their own private _Constant class). Time to revisit the PEP? All the best, Michael [1] https://launchpad.net/flufl.enum Cheers, Nick. -- http://www.voidspace.org.uk/ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, Nov 23, 2010 at 11:50 PM, Michael Foord fuzzy...@voidspace.org.uk wrote: PEP 354 was rejected for two primary reasons - lack of interest and nowhere obvious to put it. Would it be *so bad* if an enum type lived in its own module? There is certainly more interest now, and if we are to use something like this in the standard library it *has* to be in the standard library (unless every module implements their own private _Constant class). Time to revisit the PEP? If you (or anyone else) wanted to revisit the PEP, then I would advise trawling through the standard library looking for constants that could be sensibly converted to enum values. A decision would also need to be made as to whether or not to subclass int, or just provide __index__ (the former has the advantage of being able to drop cleanly into OS level APIs that expect a numerical constant). Whether enums should provide arbitrary name-value mappings (ala C enums) or were restricted to sequential indices starting from zero would be another question best addressed by a code survey of at least the stdlib. And getgeneratorstate() doesn't count as a use case, since the ordering isn't needed and using string literals instead of integers will cover the debugging aspect :) Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 23/11/2010 14:16, Nick Coghlan wrote: On Tue, Nov 23, 2010 at 11:50 PM, Michael Foord fuzzy...@voidspace.org.uk wrote: PEP 354 was rejected for two primary reasons - lack of interest and nowhere obvious to put it. Would it be *so bad* if an enum type lived in its own module? There is certainly more interest now, and if we are to use something like this in the standard library it *has* to be in the standard library (unless every module implements their own private _Constant class). Time to revisit the PEP? If you (or anyone else) wanted to revisit the PEP, then I would advise trawling through the standard library looking for constants that could be sensibly converted to enum values. A decision would also need to be made as to whether or not to subclass int, or just provide __index__ (the former has the advantage of being able to drop cleanly into OS level APIs that expect a numerical constant). Whether enums should provide arbitrary name-value mappings (ala C enums) or were restricted to sequential indices starting from zero would be another question best addressed by a code survey of at least the stdlib. And getgeneratorstate() doesn't count as a use case, since the ordering isn't needed and using string literals instead of integers will cover the debugging aspect :) Well, for backwards compatibility reasons the new constants would have to *behave* like the old ones (including having the same underlying value and comparing equal to it). In many cases it is *likely* that subclassing int is a better way of achieving that. Actually looking through the standard library to evaluate it is the only way of confirming that. Another API, that reduces the duplication of creating the enum and setting the names, could be something like: make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int, module=__name__) Using __name__ we can set the module globals in the call to make_enums. All the best, Michael Cheers, Nick. -- http://www.voidspace.org.uk/ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, 23 Nov 2010 14:24:18 + Michael Foord fuzzy...@voidspace.org.uk wrote: Well, for backwards compatibility reasons the new constants would have to *behave* like the old ones (including having the same underlying value and comparing equal to it). In many cases it is *likely* that subclassing int is a better way of achieving that. Actually looking through the standard library to evaluate it is the only way of confirming that. Another API, that reduces the duplication of creating the enum and setting the names, could be something like: make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int, module=__name__) Using __name__ we can set the module globals in the call to make_enums. I don't understand why people insist on calling that an enum. enum is a C legacy and it doesn't bring anything useful as I can tell. Instead, just assign the values explicitly. Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
2010/11/23 Antoine Pitrou solip...@pitrou.net: On Tue, 23 Nov 2010 14:24:18 + Michael Foord fuzzy...@voidspace.org.uk wrote: Well, for backwards compatibility reasons the new constants would have to *behave* like the old ones (including having the same underlying value and comparing equal to it). In many cases it is *likely* that subclassing int is a better way of achieving that. Actually looking through the standard library to evaluate it is the only way of confirming that. Another API, that reduces the duplication of creating the enum and setting the names, could be something like: make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int, module=__name__) Using __name__ we can set the module globals in the call to make_enums. I don't understand why people insist on calling that an enum. enum is a C legacy and it doesn't bring anything useful as I can tell. Instead, just assign the values explicitly. The concept of a enumeration of values is still useful outside its stunted C incarnation. Out of curiosity, why is enum legacy in C? -- Regards, Benjamin ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 23/11/2010 14:42, Antoine Pitrou wrote: On Tue, 23 Nov 2010 14:24:18 + Michael Foordfuzzy...@voidspace.org.uk wrote: Well, for backwards compatibility reasons the new constants would have to *behave* like the old ones (including having the same underlying value and comparing equal to it). In many cases it is *likely* that subclassing int is a better way of achieving that. Actually looking through the standard library to evaluate it is the only way of confirming that. Another API, that reduces the duplication of creating the enum and setting the names, could be something like: make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int, module=__name__) Using __name__ we can set the module globals in the call to make_enums. I don't understand why people insist on calling that an enum. enum is a C legacy and it doesn't bring anything useful as I can tell. Instead, just assign the values explicitly. enum isn't only in C. (They are in C# as well at least.) Wikipedia links enum to enumerated type and says: an enumerated type (also called enumeration or enum) is a data type consisting of a set of named values It sounds entirely appropriate. I have no problem with explicitly assigning values instead of doing it automagically. All the best, Michael Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk -- http://www.voidspace.org.uk/ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Le mardi 23 novembre 2010 à 08:52 -0600, Benjamin Peterson a écrit : 2010/11/23 Antoine Pitrou solip...@pitrou.net: On Tue, 23 Nov 2010 14:24:18 + Michael Foord fuzzy...@voidspace.org.uk wrote: Well, for backwards compatibility reasons the new constants would have to *behave* like the old ones (including having the same underlying value and comparing equal to it). In many cases it is *likely* that subclassing int is a better way of achieving that. Actually looking through the standard library to evaluate it is the only way of confirming that. Another API, that reduces the duplication of creating the enum and setting the names, could be something like: make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int, module=__name__) Using __name__ we can set the module globals in the call to make_enums. I don't understand why people insist on calling that an enum. enum is a C legacy and it doesn't bring anything useful as I can tell. Instead, just assign the values explicitly. The concept of a enumeration of values is still useful outside its stunted C incarnation. Well, it is easy to assign range(N) to a tuple of names when desired. I don't think an automatically-enumerating constant generator is needed. Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Le mardi 23 novembre 2010 à 14:56 +, Michael Foord a écrit : On 23/11/2010 14:42, Antoine Pitrou wrote: On Tue, 23 Nov 2010 14:24:18 + Michael Foordfuzzy...@voidspace.org.uk wrote: Well, for backwards compatibility reasons the new constants would have to *behave* like the old ones (including having the same underlying value and comparing equal to it). In many cases it is *likely* that subclassing int is a better way of achieving that. Actually looking through the standard library to evaluate it is the only way of confirming that. Another API, that reduces the duplication of creating the enum and setting the names, could be something like: make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int, module=__name__) Using __name__ we can set the module globals in the call to make_enums. I don't understand why people insist on calling that an enum. enum is a C legacy and it doesn't bring anything useful as I can tell. Instead, just assign the values explicitly. enum isn't only in C. (They are in C# as well at least.) Well, it's been inherited by C-like languages, no doubt. Like braces and semicolumns :) Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 23/11/2010 15:01, Antoine Pitrou wrote: Le mardi 23 novembre 2010 à 08:52 -0600, Benjamin Peterson a écrit : 2010/11/23 Antoine Pitrousolip...@pitrou.net: On Tue, 23 Nov 2010 14:24:18 + Michael Foordfuzzy...@voidspace.org.uk wrote: Well, for backwards compatibility reasons the new constants would have to *behave* like the old ones (including having the same underlying value and comparing equal to it). In many cases it is *likely* that subclassing int is a better way of achieving that. Actually looking through the standard library to evaluate it is the only way of confirming that. Another API, that reduces the duplication of creating the enum and setting the names, could be something like: make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int, module=__name__) Using __name__ we can set the module globals in the call to make_enums. I don't understand why people insist on calling that an enum. enum is a C legacy and it doesn't bring anything useful as I can tell. Instead, just assign the values explicitly. The concept of a enumeration of values is still useful outside its stunted C incarnation. Well, it is easy to assign range(N) to a tuple of names when desired. I don't think an automatically-enumerating constant generator is needed. Right, and that is current practise. It has the disadvantage (that you seemed to acknowledge) that when debugging the integer values are seen instead of something with a useful repr. Having a *simple* class (and API to create them) that produces named constants with a useful repr, is what we are discussing, and that seems awfully like an enum (in the general sense not in a C specific sense). For backwards compatibility these constants, where they replace integer constants, would need to be integer subclasses with the same behaviour. Like the Qt example you appreciated so much. ;-) There are still two reasonable APIs (unless you have changed your mind and think that sticking with plain integers is best), of which I prefer the latter: SOME_CONST = Constant('SOME_CONST', 1) OTHER_CONST = Constant('OTHER_CONST', 2) or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1) SOME_CONST = Constants.SOME_CONST OTHER_CONST = Constants.OTHER_CONST (Well, there is a third option that takes __name__ and sets the constants in the module automagically. I can understand why people would dislike that though.) All the best, Michael Foord Michael Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk -- http://www.voidspace.org.uk/ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Le mardi 23 novembre 2010 à 15:15 +, Michael Foord a écrit : There are still two reasonable APIs (unless you have changed your mind and think that sticking with plain integers is best), of which I prefer the latter: SOME_CONST = Constant('SOME_CONST', 1) OTHER_CONST = Constant('OTHER_CONST', 2) or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1) Or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', values=range(1, 3)) Again, auto-enumeration is useless since it's trivial to achieve explicitly. Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 23/11/2010 15:30, Antoine Pitrou wrote: Le mardi 23 novembre 2010 à 15:15 +, Michael Foord a écrit : There are still two reasonable APIs (unless you have changed your mind and think that sticking with plain integers is best), of which I prefer the latter: SOME_CONST = Constant('SOME_CONST', 1) OTHER_CONST = Constant('OTHER_CONST', 2) or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1) Or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', values=range(1, 3)) Again, auto-enumeration is useless since it's trivial to achieve explicitly. Ah, I see. It is the auto-enumeration you disliked. Sure - not a problem. I think the step that Nick described, of evaluating places in the standard library that this could be used, is a good one. I'll try to get around to it and perhaps attempt to resuscitate the PEP. (Any suggestions as to an appropriate module if having it live in its own module is still an objection?) Michael Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Le mardi 23 novembre 2010 à 15:40 +, Michael Foord a écrit : On 23/11/2010 15:30, Antoine Pitrou wrote: Le mardi 23 novembre 2010 à 15:15 +, Michael Foord a écrit : There are still two reasonable APIs (unless you have changed your mind and think that sticking with plain integers is best), of which I prefer the latter: SOME_CONST = Constant('SOME_CONST', 1) OTHER_CONST = Constant('OTHER_CONST', 2) or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1) Or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', values=range(1, 3)) Again, auto-enumeration is useless since it's trivial to achieve explicitly. Ah, I see. It is the auto-enumeration you disliked. Sure - not a problem. I think the step that Nick described, of evaluating places in the standard library that this could be used, is a good one. I'll try to get around to it and perhaps attempt to resuscitate the PEP. (Any suggestions as to an appropriate module if having it live in its own module is still an objection?) We already have a bunch of bizarrely unrelated stuff in collections (such as Callable), so we could put enum there too. Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 23/11/2010 16:05, Antoine Pitrou wrote: Le mardi 23 novembre 2010 à 15:40 +, Michael Foord a écrit : On 23/11/2010 15:30, Antoine Pitrou wrote: Le mardi 23 novembre 2010 à 15:15 +, Michael Foord a écrit : There are still two reasonable APIs (unless you have changed your mind and think that sticking with plain integers is best), of which I prefer the latter: SOME_CONST = Constant('SOME_CONST', 1) OTHER_CONST = Constant('OTHER_CONST', 2) or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1) Or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', values=range(1, 3)) Again, auto-enumeration is useless since it's trivial to achieve explicitly. Ah, I see. It is the auto-enumeration you disliked. Sure - not a problem. I think the step that Nick described, of evaluating places in the standard library that this could be used, is a good one. I'll try to get around to it and perhaps attempt to resuscitate the PEP. (Any suggestions as to an appropriate module if having it live in its own module is still an objection?) We already have a bunch of bizarrely unrelated stuff in collections (such as Callable), so we could put enum there too. I guess it creates collections of constants... Michael Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, 23 Nov 2010 15:15:29 +, Michael Foord wrote: There are still two reasonable APIs (unless you have changed your mind and think that sticking with plain integers is best), of which I prefer the latter: SOME_CONST = Constant('SOME_CONST', 1) OTHER_CONST = Constant('OTHER_CONST', 2) or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1) SOME_CONST = Constants.SOME_CONST OTHER_CONST = Constants.OTHER_CONST I prefer the latter too, because that makes it possible to have 'Constants' be a rendezvous point for making sure that you're passing something valid. Perhaps using 'in': def func(foo): if foo not in Constants: raise ValueError('foo must be SOME_CONST or OTHER_CONST') ... I know this is probably not going to happen, but I would *so much* like it if functions would start rejecting the wrong kind of 2. Constants that are valid, integer-wise, but which aren't part of the set of constants allowed for that argument. I'd prefer not to think of the number of times I've made the following mistake: s = socket.socket(socket.SOCK_DGRAM, socket.AF_INET) ~Ben ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 23/11/2010 15:37, ben.cottr...@nominum.com wrote: On Tue, 23 Nov 2010 15:15:29 +, Michael Foord wrote: There are still two reasonable APIs (unless you have changed your mind and think that sticking with plain integers is best), of which I prefer the latter: SOME_CONST = Constant('SOME_CONST', 1) OTHER_CONST = Constant('OTHER_CONST', 2) or: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1) SOME_CONST = Constants.SOME_CONST OTHER_CONST = Constants.OTHER_CONST I prefer the latter too, because that makes it possible to have 'Constants' be a rendezvous point for making sure that you're passing something valid. Perhaps using 'in': def func(foo): if foo not in Constants: raise ValueError('foo must be SOME_CONST or OTHER_CONST') ... I know this is probably not going to happen, but I would *so much* like it if functions would start rejecting the wrong kind of 2. Constants that are valid, integer-wise, but which aren't part of the set of constants allowed for that argument. I'd prefer not to think of the number of times I've made the following mistake: s = socket.socket(socket.SOCK_DGRAM, socket.AF_INET) Well it would be perfectly possible for the __contains__ method (on the metaclass so that a Constants class can act as a container) to permit a *raw integer* (to be backwards compatible with code using hard coded values) but not permit other constants that aren't valid. Code that is *deliberately* using the wrong constants would be screwed of course... All the best, Michael ~Ben ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Nov 23, 2010, at 01:50 PM, Michael Foord wrote: Right. As it happens I just submitted a patch to Barry Warsaw's enum package (nice), flufl.enum [1], to allow namedtuple style creation of named constants: Thanks for the plug (and the nice patch). FWIW, the documentation for the package is here: http://packages.python.org/flufl.enum/ I made some explicit decisions about the API and semantics of this package, to fit my own use cases and sensibilities. I guess you wouldn't expect anything else wink, but I'm willing to acknowledge that others would make different decisions, and certainly the number of existing enum implementations out there proves that there are lots of interesting ways to go about it. That said, there are several things I like about my package: * Enums are not subclassed from ints or strs. They are a distinct data type that can be converted to and from ints and strs. EIBTI. * The typical way to create them is through a simple, but explicit class definition. I personally like being explicit about the item values, and the assignments are required to make the metaclass work properly, but Michael's convenience patch is totally appropriate for cases where you don't care, or you want a one-liner. * Enum items are singletons and are intended to be compared by identity. They can be compared by equality but are not ordered. * Enum items have an unambiguous symbolic repr and a nice human readable str. * Given an enum item, you can get to its enum class, and given the class you can get to the set of items. * Enums can be subclassed (though all items in the subclass must have unique values). In any case it may be that enums are too tied to specific use cases to find a good common ground for the stdlib. I've been using my module for years and if there's interest I would of course be happy to donate it for use in the stdlib. Like the original sets implementation, it makes perfect sense to provide them in a separate module rather than as a built-in type. -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Nov 23, 2010, at 03:15 PM, Michael Foord wrote: (Well, there is a third option that takes __name__ and sets the constants in the module automagically. I can understand why people would dislike that though.) Personally, I think if you want that, then the explicit class definition is a better way to go. -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
At 11:31 AM 11/23/2010 -0500, Barry Warsaw wrote: On Nov 23, 2010, at 03:15 PM, Michael Foord wrote: (Well, there is a third option that takes __name__ and sets the constants in the module automagically. I can understand why people would dislike that though.) Personally, I think if you want that, then the explicit class definition is a better way to go. This reminds me: a stdlib enum should support proper pickling and copying; i.e.: assert SomeEnum.anEnum is pickle.loads(pickle.dumps(SomeEnum.anEnum)) This could probably be implemented by adding something like: def __reduce__(self): return getattr, (self._class, self._enumname) in the EnumValue class. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 23/11/2010 16:27, Barry Warsaw wrote: On Nov 23, 2010, at 01:50 PM, Michael Foord wrote: Right. As it happens I just submitted a patch to Barry Warsaw's enum package (nice), flufl.enum [1], to allow namedtuple style creation of named constants: Thanks for the plug (and the nice patch). FWIW, the documentation for the package is here: http://packages.python.org/flufl.enum/ I made some explicit decisions about the API and semantics of this package, to fit my own use cases and sensibilities. I guess you wouldn't expect anything elsewink, but I'm willing to acknowledge that others would make different decisions, and certainly the number of existing enum implementations out there proves that there are lots of interesting ways to go about it. That said, there are several things I like about my package: * Enums are not subclassed from ints or strs. They are a distinct data type that can be converted to and from ints and strs. EIBTI. But if we are to use it *in* the standard library (as opposed to merely adding a module *to* the standard library) there are backwards compatibility concerns. Where modules are already using integers for constants then integers still need to work. One easy way to achieve this is to subclass integer. If we don't do that (assuming we decide that putting a solution in the standard library is appropriate) then we'll have to evaluate what we mean by backwards compatible. If the modules that use the constants aren't to change then comparing equal to the underlying value is the minimum (so that the original value can still be used in place of the new named constant). Not sure if you'd be happy to make that change in flufl.enum. * The typical way to create them is through a simple, but explicit class definition. I personally like being explicit about the item values, and the assignments are required to make the metaclass work properly, but Michael's convenience patch is totally appropriate for cases where you don't care, or you want a one-liner. If make_enum was to take a set of values to use (as Antoine suggested) I don't see what's un-explicit about it. All the best, Michael * Enum items are singletons and are intended to be compared by identity. They can be compared by equality but are not ordered. * Enum items have an unambiguous symbolic repr and a nice human readable str. * Given an enum item, you can get to its enum class, and given the class you can get to the set of items. * Enums can be subclassed (though all items in the subclass must have unique values). In any case it may be that enums are too tied to specific use cases to find a good common ground for the stdlib. I've been using my module for years and if there's interest I would of course be happy to donate it for use in the stdlib. Like the original sets implementation, it makes perfect sense to provide them in a separate module rather than as a built-in type. -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (BOGUS AGREEMENTS) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Le mardi 23 novembre 2010 à 12:32 -0500, Isaac Morland a écrit : On Tue, 23 Nov 2010, Antoine Pitrou wrote: We already have a bunch of bizarrely unrelated stuff in collections (such as Callable), so we could put enum there too. Why not just enum (i.e., from enum import [...] or import enum.[...])? Enumerations are one of the basic kinds of types overall (speaking informally and independent of any specific language) - they aren't at all exotic. Enumerations aren't a type at all (they have no distinguishing property). And Flat is better than nested, after all. Not when it means creating a separate module for every micro-feature. Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, 23 Nov 2010, Antoine Pitrou wrote: We already have a bunch of bizarrely unrelated stuff in collections (such as Callable), so we could put enum there too. Why not just enum (i.e., from enum import [...] or import enum.[...])? Enumerations are one of the basic kinds of types overall (speaking informally and independent of any specific language) - they aren't at all exotic. And Flat is better than nested, after all. Isaac Morland CSCF Web Guru DC 2554C, x36650WWW Software Specialist ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, 23 Nov 2010, Antoine Pitrou wrote: Le mardi 23 novembre 2010 à 12:32 -0500, Isaac Morland a écrit : On Tue, 23 Nov 2010, Antoine Pitrou wrote: We already have a bunch of bizarrely unrelated stuff in collections (such as Callable), so we could put enum there too. Why not just enum (i.e., from enum import [...] or import enum.[...])? Enumerations are one of the basic kinds of types overall (speaking informally and independent of any specific language) - they aren't at all exotic. Enumerations aren't a type at all (they have no distinguishing property). Each enumeration is a type (well, OK, not in every language, presumably, but certainly in many languages). The word basic is more important than types in my sentence - the point is that an enumeration capability is a very common one in a type system, and is very general, not specific to any particular application. And Flat is better than nested, after all. Not when it means creating a separate module for every micro-feature. Classes have their own keyword. I don't think it's disproportionate to give enums a top-level module name. Having said that, I understand we're trying to have a not-too-flat module namespace and I can see the sense in putting it in collections. But I think the idea that enumerations are of very wide applicability and hence deserve a shorter name should be seriously considered. I'll leave it at that, except for: Hey, how about this syntax: enum Colors: red = 0 green = 10 blue (blue gets the value 11) ;-) Isaac Morland CSCF Web Guru DC 2554C, x36650WWW Software Specialist___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, Nov 23, 2010 at 12:37 PM, Antoine Pitrou solip...@pitrou.net wrote: Enumerations aren't a type at all (they have no distinguishing property). In any given language, this may be true, or not. Whether they should be distinct in Python is core to the current discussion. From a backward-compatibility perspective, what makes sense depends on whether they're used to implement existing constants (socket.AF_INET, etc.) or if they reserved for new features only. -Fred -- Fred L. Drake, Jr. fdrake at acm.org A storm broke loose in my mind. --Albert Einstein ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Le mardi 23 novembre 2010 à 12:57 -0500, Fred Drake a écrit : On Tue, Nov 23, 2010 at 12:37 PM, Antoine Pitrou solip...@pitrou.net wrote: Enumerations aren't a type at all (they have no distinguishing property). In any given language, this may be true, or not. Whether they should be distinct in Python is core to the current discussion. I meant type in the structural sense (hence the parenthesis). enums are just auto-generated constants. Since Python makes it trivial to generate sequential integers, there's no need for a specific enum construct. Now you may argue that enums should be strongly-typed, but that would be a bit backwards given Python's preference for duck-typing. From a backward-compatibility perspective, what makes sense depends on whether they're used to implement existing constants (socket.AF_INET, etc.) or if they reserved for new features only. It's not only backwards compatibility. New features relying on C APIs have to be able to map constants to the integers used in the C library. It would be much better if this were done naturally rather than through explicit conversion maps. (this really means subclassing int, if we don't want to complicate C-level code) Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Le mardi 23 novembre 2010 à 12:50 -0500, Isaac Morland a écrit : Each enumeration is a type (well, OK, not in every language, presumably, but certainly in many languages). The word basic is more important than types in my sentence - the point is that an enumeration capability is a very common one in a type system, and is very general, not specific to any particular application. Python already has an enumeration capability. It's called range(). There's nothing else that C enums have. AFAICT, neither do enums in other mainstream languages (assuming they even exist; I don't remember Perl, PHP or Javascript having anything like that, but perhaps I'm mistaken). Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Isaac Morland ijmor...@uwaterloo.ca wrote: On Tue, 23 Nov 2010, Antoine Pitrou wrote: Le mardi 23 novembre 2010 à 12:32 -0500, Isaac Morland a écrit : On Tue, 23 Nov 2010, Antoine Pitrou wrote: We already have a bunch of bizarrely unrelated stuff in collections (such as Callable), so we could put enum there too. Why not just enum (i.e., from enum import [...] or import enum.[...])? Enumerations are one of the basic kinds of types overall (speaking informally and independent of any specific language) - they aren't at all exotic. Enumerations aren't a type at all (they have no distinguishing property). Not in C, but in some other languages. Each enumeration is a type (well, OK, not in every language, presumably, but certainly in many languages). The main purpose of that is to be able to catch type mismatches with static typing, though. Seems kind of pointless for Python. Classes have their own keyword. I don't think it's disproportionate to give enums a top-level module name. I do. Hey, how about this syntax: enum Colors: red = 0 green = 10 blue Why not class Color: red = (255, 0, 0) green = (0, 255, 0) blue = (0, 0, 255) Seems to handle the situation OK. Bill ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, Nov 23, 2010 at 10:06 AM, Antoine Pitrou solip...@pitrou.net wrote: Le mardi 23 novembre 2010 à 12:57 -0500, Fred Drake a écrit : On Tue, Nov 23, 2010 at 12:37 PM, Antoine Pitrou solip...@pitrou.net wrote: Enumerations aren't a type at all (they have no distinguishing property). In any given language, this may be true, or not. Whether they should be distinct in Python is core to the current discussion. I meant type in the structural sense (hence the parenthesis). enums are just auto-generated constants. Since Python makes it trivial to generate sequential integers, there's no need for a specific enum construct. Now you may argue that enums should be strongly-typed, but that would be a bit backwards given Python's preference for duck-typing. Please take a step back. The best example of the utility of enums even for Python is bool. I resisted this for the longest time but people kept asking for it. Some properties of bool: (a) bool is a (final) subclass of int, and an int is acceptable in a pinch where a bool is expected (b) bool values are guaranteed unique -- there is only one instance with value True, and only one with value False (c) bool values have a str() and repr() that shows their name instead of their value (but not their class -- that's rarely an issue, and makes the output more compact) I think it makes sense to add a way to the stdlib to add other types like bool. I think (c) is probably the most important feature, followed by (a) -- except the *final* part: I want to subclass enums. (b) is probably easy to do but I don't think it matters that much in practice. From a backward-compatibility perspective, what makes sense depends on whether they're used to implement existing constants (socket.AF_INET, etc.) or if they reserved for new features only. It's not only backwards compatibility. New features relying on C APIs have to be able to map constants to the integers used in the C library. It would be much better if this were done naturally rather than through explicit conversion maps. I'm not sure what you mean here. Can you give an example of what you mean? I agree that it should be possible to make pretty much any constant in the OS modules enums -- even if the values vary across platforms. (this really means subclassing int, if we don't want to complicate C-level code) Right. FWIW I don't think I'm particular about the exact API to construct a new enum type in Python code; I think in most cases explicitly assigning values is fine. Often the values are constrained by something external anyway; it should be easy to dynamically set the values of a particular enum type (even add new values after the fact). There might also be enums with the same value (even though the mapping from int to enum will then have to pick one). I expect that the API to convert between enums and bare ints should be i = int(e) and e = enumclass(i). It would be nice if s = str(e) and e = enumclass(s) would work too. -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Nov 23, 2010, at 12:57 PM, Fred Drake wrote: From a backward-compatibility perspective, what makes sense depends on whether they're used to implement existing constants (socket.AF_INET, etc.) or if they reserved for new features only. As is usually the case, there's little reason to change existing working code. Enums can be used whenever a module or API is updated. -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Nov 23, 2010, at 05:02 PM, Michael Foord wrote: * Enums are not subclassed from ints or strs. They are a distinct data type that can be converted to and from ints and strs. EIBTI. But if we are to use it *in* the standard library (as opposed to merely adding a module *to* the standard library) there are backwards compatibility concerns. Where modules are already using integers for constants then integers still need to work. Is int(enum_value) enough, or must the enum value actually *be* an int? One easy way to achieve this is to subclass integer. If we don't do that (assuming we decide that putting a solution in the standard library is appropriate) then we'll have to evaluate what we mean by backwards compatible. If the modules that use the constants aren't to change then comparing equal to the underlying value is the minimum (so that the original value can still be used in place of the new named constant). Not sure if you'd be happy to make that change in flufl.enum. I'm not sure either. In flufl.enum enum_class(i) also works as expected. * The typical way to create them is through a simple, but explicit class definition. I personally like being explicit about the item values, and the assignments are required to make the metaclass work properly, but Michael's convenience patch is totally appropriate for cases where you don't care, or you want a one-liner. If make_enum was to take a set of values to use (as Antoine suggested) I don't see what's un-explicit about it. When I saw your patch I immediately thought that I could add a default argument that was something like `int_iter`, i.e. an iterator of integers for the values in the string. I suspect YAGNI, which is why I didn't just add it, but I'm not totally opposed to it. -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Nov 23, 2010, at 11:52 AM, P.J. Eby wrote: This reminds me: a stdlib enum should support proper pickling and copying; i.e.: assert SomeEnum.anEnum is pickle.loads(pickle.dumps(SomeEnum.anEnum)) This could probably be implemented by adding something like: def __reduce__(self): return getattr, (self._class, self._enumname) in the EnumValue class. Excellent idea, thanks. Added to flufl.enum in r38. However, only enums created with the class syntax can be pickled though. Cheers, -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, Nov 23, 2010 at 11:47 AM, Barry Warsaw ba...@python.org wrote: On Nov 23, 2010, at 05:02 PM, Michael Foord wrote: * Enums are not subclassed from ints or strs. They are a distinct data type that can be converted to and from ints and strs. EIBTI. But if we are to use it *in* the standard library (as opposed to merely adding a module *to* the standard library) there are backwards compatibility concerns. Where modules are already using integers for constants then integers still need to work. Is int(enum_value) enough, or must the enum value actually *be* an int? I vote for *be*, following bool's example. One easy way to achieve this is to subclass integer. If we don't do that (assuming we decide that putting a solution in the standard library is appropriate) then we'll have to evaluate what we mean by backwards compatible. If the modules that use the constants aren't to change then comparing equal to the underlying value is the minimum (so that the original value can still be used in place of the new named constant). Not sure if you'd be happy to make that change in flufl.enum. I'm not sure either. In flufl.enum enum_class(i) also works as expected. * The typical way to create them is through a simple, but explicit class definition. I personally like being explicit about the item values, and the assignments are required to make the metaclass work properly, but Michael's convenience patch is totally appropriate for cases where you don't care, or you want a one-liner. If make_enum was to take a set of values to use (as Antoine suggested) I don't see what's un-explicit about it. When I saw your patch I immediately thought that I could add a default argument that was something like `int_iter`, i.e. an iterator of integers for the values in the string. I suspect YAGNI, which is why I didn't just add it, but I'm not totally opposed to it. -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/guido%40python.org -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 11/23/2010 11:34 AM, Guido van Rossum wrote: The best example of the utility of enums even for Python is bool. I resisted this for the longest time but people kept asking for it. Some properties of bool: (a) bool is a (final) subclass of int, and an int is acceptable in a pinch where a bool is expected (b) bool values are guaranteed unique -- there is only one instance with value True, and only one with value False (c) bool values have a str() and repr() that shows their name instead of their value (but not their class -- that's rarely an issue, and makes the output more compact) I think it makes sense to add a way to the stdlib to add other types like bool. I think (c) is probably the most important feature, followed by (a) -- except the *final* part: I want to subclass enums. (b) is probably easy to do but I don't think it matters that much in practice. I was concerned about uniqueness constraints some were touting. While that can be a useful property for some enumerations, it can also be convenient for other enumerations to have multiple names map to the same value. Bool seems appropriately not extensible to additional values. While there are tri-valued (and other) logic systems, they deserve a separate namespace. Bool seems to be an example, then of a set of distingushed names, with values associated to the names, and is restricted to [two] [unique] integer values. C/C++/C# enum is somewhat like that, and is also restricted to integer values [not necessarily unique]. I wonder if a set of distinguished names need to be restricted to integer values to be useful, although I have no doubt that distinguished names with integer values are useful. Someone used an example of color names class having RGB tuple values, which is a counter example to a restriction to integers. I can think of others as well. Perhaps a set of distinguished names, with values associated to the names is really a dict, with the unique names restricted to Python identifier syntax (to be useful), and the values unrestricted. The type of the named value, and the value of the named value, seem not to need to be restricted. But the implementations Bool = dict('False': 0, 'True': 1) or alternately class Bool(): self.False = 0 self.True = 1 is missing a couple characteristics of Python's present bool: the names are not special, and the values are not immutable. Perhaps games could be played to make the second implementation effectively immutable. So I think the real trick of the enum (or a generalized distinguished names) is in the naming. A technique to import the keys that are legal Python identifiers from a dict into a namespace, and retain henceforth immutable values for those names would permit the syntactical usage that people are accustomed to from the C/C++/C# enum, but with extended ranges and types of values, and it seems Bool could be mostly reimplemented via that technique. What is still missing? The debugging help: the values, once imported, should not become just values of their type, but rather a new type of value, that has an associated name (and type, I think). Whatever magic is worked under the covers to make sure that there is just one True and just one False, so that they can be distinguished from the values 1 and 0, and so reported, should also be applied to these values. So there need not be new syntax for creating the name/value pairs; just use dict. The only new API would be the code that imports the dict into the local namespace. Note that other scoped definitions of True and False are not possible today because True and False are keywords. It would be inappropriate to define these distinguished names as all being keywords, so it seems like one could still override the names, even once defined, but such overridden names would lose their special value that makes them a distinguished name. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Le mardi 23 novembre 2010 à 11:34 -0800, Guido van Rossum a écrit : From a backward-compatibility perspective, what makes sense depends on whether they're used to implement existing constants (socket.AF_INET, etc.) or if they reserved for new features only. It's not only backwards compatibility. New features relying on C APIs have to be able to map constants to the integers used in the C library. It would be much better if this were done naturally rather than through explicit conversion maps. I'm not sure what you mean here. Can you give an example of what you mean? I agree that it should be possible to make pretty much any constant in the OS modules enums -- even if the values vary across platforms. I mean that PyArg_ParseTuple should continue to be pratical even if e.g. os.SEEK_SET and friends become named constants. It implies that the various format codes such as i, l, etc. are still usable with those constants. Hence: (this really means subclassing int, if we don't want to complicate C-level code) Right. :-) Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 11/23/2010 12:07 PM, Antoine Pitrou wrote: Le mardi 23 novembre 2010 à 12:50 -0500, Isaac Morland a écrit : Each enumeration is a type (well, OK, not in every language, presumably, but certainly in many languages). The word basic is more important than types in my sentence - the point is that an enumeration capability is a very common one in a type system, and is very general, not specific to any particular application. Python already has an enumeration capability. It's called range(). There's nothing else that C enums have. AFAICT, neither do enums in other mainstream languages (assuming they even exist; I don't remember Perl, PHP or Javascript having anything like that, but perhaps I'm mistaken). Aren't we forgetting enumerate? colors = 'BLACK BROWN RED ORANGE YELLOW GREEN BLUE VIOLET GREY WHITE' dict(e for e in enumerate(colors.split())) {0: 'BLACK', 1: 'BROWN', 2: 'RED', 3: 'ORANGE', 4: 'YELLOW', 5: 'GREEN', 6: 'BLUE', 7: 'VIOLET', 8: 'GREY', 9: 'WHITE'} dict((f, n) for (n, f) in enumerate(colors.split())) {'BLUE': 6, 'BROWN': 1, 'GREY': 8, 'YELLOW': 4, 'GREEN': 5, 'VIOLET': 7, 'ORANGE': 3, 'BLACK': 0, 'WHITE': 9, 'RED': 2} Most other languages that use numbered constants number them by base n^2. [x**2 for x in range(10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] Binary flags have the advantage of saving memory because you can assign more than one to a single integer. Another advantage is other languages use them so it can make it easier interface with them. There also may be some performance advantages as well since you can test for multiple flags with a single comparison. Sets of strings can also work when you don't need to associate a numeric value to the constant. ie... the constant is the value. In this case the set supplies the api. Cheers, Ron ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Nov 23, 2010, at 10:37 AM, ben.cottr...@nominum.com wrote: I'd prefer not to think of the number of times I've made the following mistake: s = socket.socket(socket.SOCK_DGRAM, socket.AF_INET) If it's any consolation, it's fewer than the number of times I have :). (More fun, actually, is where you pass a file descriptor to the wrong argument of 'fromfd'...) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Antoine Pitrou wrote: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', values=range(1, 3)) Again, auto-enumeration is useless since it's trivial to achieve explicitly. That doesn't make auto-enumeration useless. Unnecessary, perhaps, but not useless. But even then it's only unnecessary if the number of constants are small enough that you can see how many there are without counting (essentially, 4 or fewer). When you have more, it becomes error-prone and a nuisance to have to count them by hand: Constants = make_constants( 'Constants', 'ST_MODE ST_INO ST_DEV ST_NLINK ST_UID ST_GID' \ 'ST_SIZE ST_ATIME ST_MTIME ST_CTIME', values=range(10) ) -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Nov 23, 2010, at 10:01 AM, Antoine Pitrou wrote: Well, it is easy to assign range(N) to a tuple of names when desired. I don't think an automatically-enumerating constant generator is needed. I don't think that numerical enumerations are the only kind of constants we're talking about. Others have already mentioned strings. Also, see http://tm.tl/4671 for some other use-cases. Since this isn't coming to 2.x, we're probably going to do our own thing anyway (unless it turns out that flufl.enum is so great that we want to add another dependency...) but I'm hoping that the outcome of this discussion will point to something we can be compatible with. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Le mardi 23 novembre 2010 à 16:10 -0500, Glyph Lefkowitz a écrit : On Nov 23, 2010, at 10:01 AM, Antoine Pitrou wrote: Well, it is easy to assign range(N) to a tuple of names when desired. I don't think an automatically-enumerating constant generator is needed. I don't think that numerical enumerations are the only kind of constants we're talking about. Others have already mentioned strings. Also, see http://tm.tl/4671 for some other use-cases. Since this isn't coming to 2.x, we're probably going to do our own thing anyway (unless it turns out that flufl.enum is so great that we want to add another dependency...) but I'm hoping that the outcome of this discussion will point to something we can be compatible with. I think that asking for too many features would get in the way, and also make the API quite un-Pythonic. If you want your values to be e.g. OR'able, just choose your values wisely ;) Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Oops.. x**2 should have been 2**x below. On 11/23/2010 03:03 PM, Ron Adam wrote: On 11/23/2010 12:07 PM, Antoine Pitrou wrote: Le mardi 23 novembre 2010 à 12:50 -0500, Isaac Morland a écrit : Each enumeration is a type (well, OK, not in every language, presumably, but certainly in many languages). The word basic is more important than types in my sentence - the point is that an enumeration capability is a very common one in a type system, and is very general, not specific to any particular application. Python already has an enumeration capability. It's called range(). There's nothing else that C enums have. AFAICT, neither do enums in other mainstream languages (assuming they even exist; I don't remember Perl, PHP or Javascript having anything like that, but perhaps I'm mistaken). Aren't we forgetting enumerate? colors = 'BLACK BROWN RED ORANGE YELLOW GREEN BLUE VIOLET GREY WHITE' dict(e for e in enumerate(colors.split())) {0: 'BLACK', 1: 'BROWN', 2: 'RED', 3: 'ORANGE', 4: 'YELLOW', 5: 'GREEN', 6: 'BLUE', 7: 'VIOLET', 8: 'GREY', 9: 'WHITE'} dict((f, n) for (n, f) in enumerate(colors.split())) {'BLUE': 6, 'BROWN': 1, 'GREY': 8, 'YELLOW': 4, 'GREEN': 5, 'VIOLET': 7, 'ORANGE': 3, 'BLACK': 0, 'WHITE': 9, 'RED': 2} Most other languages that use numbered constants number them by base n^2. [x**2 for x in range(10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] [2**x for x in range(10)] [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] Binary flags have the advantage of saving memory because you can assign more than one to a single integer. Another advantage is other languages use them so it can make it easier interface with them. There also may be some performance advantages as well since you can test for multiple flags with a single comparison. Sets of strings can also work when you don't need to associate a numeric value to the constant. ie... the constant is the value. In this case the set supplies the api. Cheers, Ron ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/python-python-dev%40m.gmane.org ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Antoine Pitrou wrote: Python already has an enumeration capability. It's called range(). There's nothing else that C enums have. AFAICT, neither do enums in other mainstream languages (assuming they even exist; I don't remember Perl, PHP or Javascript having anything like that, but perhaps I'm mistaken). In Pascal, enumerations are a type, and the value of the named values are an implementation detail. E.g. one would define an enumerated type: type flavour = (sweet, salty, sour, bitter, umame); var x: flavour; and then you would write something like: x := sour; Notice that the constants sweet etc. aren't explicitly predefined, since they're purely internal details and the compiler is allowed to number them any way it likes. In Python, we would need stronger guarantees about the values chosen, so that they could be exposed to external modules, pickled, etc. But that doesn't mean we should be forced to specify the values ourselves. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Antoine Pitrou wrote: I don't understand why people insist on calling that an enum. enum is a C legacy and it doesn't bring anything useful as I can tell. The usefulness is that they can have a str() or repr() that displays the name of the value instead of an integer. The bool type was added for much the same reason -- otherwise we would simply have gotten builtin names False = 0 and True = 1. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Antoine Pitrou wrote: Well, it's been inherited by C-like languages, no doubt. Like braces and semicolumns :) The idea isn't confined to the C family. Pascal and many of the languages inspired by it also have enumerated types. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, 23 Nov 2010, Bill Janssen wrote: The main purpose of that is to be able to catch type mismatches with static typing, though. Seems kind of pointless for Python. The concept can work dynamically. In fact, the flufl.enum package which has been discussed here makes each enumeration into a separate class so many of the advantages of catching type mismatches are obtained. Hey, how about this syntax: enum Colors: red = 0 green = 10 blue Why not class Color: red = (255, 0, 0) green = (0, 255, 0) blue = (0, 0, 255) Seems to handle the situation OK. Yes, this looks almost exactly like flufl.enum syntax. In any case my suggestion of a new keyword was not meant to be taken seriously. If I ever think I have a good reason to suggest a new keyword I'll sleep on it, take a vacation, and then if I still think a new keyword is justified I will specifically disclaim any possibility of the suggestion being a joke. Isaac Morland CSCF Web Guru DC 2554C, x36650WWW Software Specialist ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Antoine Pitrou wrote: I think that asking for too many features would get in the way, and also make the API quite un-Pythonic. If you want your values to be e.g. OR'able, just choose your values wisely ;) On the other hand it could be useful to have an easy way to request power-of-2 value assignment, seeing as it's another common pattern. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Bill Janssen wrote: The main purpose of that is to be able to catch type mismatches with static typing, though. Seems kind of pointless for Python. But catching type mismatches with dynamic typing doesn't seem pointless for Python. There's nothing static about the proposals being made here that I can see. Why not class Color: red = (255, 0, 0) green = (0, 255, 0) blue = (0, 0, 255) If all you want is a bunch of named constants, that's fine. But the facilities being discussed here are designed to give you other things as well, such as c = Color.red print(c) printing red rather than (255, 0, 0). -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Antoine Pitrou wrote: Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', values=range(1, 3)) Again, auto-enumeration is useless since it's trivial to achieve explicitly. But seeing as it's going to be a common thing to do, why not make it the default? When defining an enum, often you don't *care* what the underlying values are, so assigning sequential natural numbers is as good a default as any. In fact, with the Pascal concept of an enumerated type you don't get any choice in the matter. It's only in the C family that you get this bastardised conflation of enumerations with arbitrary named constants... -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
Isaac Morland wrote: In any case my suggestion of a new keyword was not meant to be taken seriously. I don't think it need be taken entirely as a joke, either. All the proposed patterns for creating enums that I've seen end up leaving something to be desired. They violate DRY by requiring you to write the class name twice, or they make you write the names of the values in quotes, or some other minor ugliness. While it may be possible to work around these things with sufficient levels of metaclass hackery and black magic, at some point one has to consider whether new syntax might be the least worst option. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On 23/11/2010 21:15, Antoine Pitrou wrote: Le mardi 23 novembre 2010 à 16:10 -0500, Glyph Lefkowitz a écrit : On Nov 23, 2010, at 10:01 AM, Antoine Pitrou wrote: Well, it is easy to assign range(N) to a tuple of names when desired. I don't think an automatically-enumerating constant generator is needed. I don't think that numerical enumerations are the only kind of constants we're talking about. Others have already mentioned strings. Also, seehttp://tm.tl/4671 for some other use-cases. Since this isn't coming to 2.x, we're probably going to do our own thing anyway (unless it turns out that flufl.enum is so great that we want to add another dependency...) but I'm hoping that the outcome of this discussion will point to something we can be compatible with. I think that asking for too many features would get in the way, and also make the API quite un-Pythonic. If you want your values to be e.g. OR'able, just choose your values wisely ;) Well, the point of an OR'able flag is that the result shows the OR'd values in the repr. Raymond suggests using a set of strings where you need flag constants. For new apis (so no backwards compatibility constraints) where you don't need to use integers (i.e. not wrapping a C library) that's a great suggestion: flags = {'FOO', 'BAR'} Michael Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk -- http://www.voidspace.org.uk/ READ CAREFULLY. By accepting and reading this email you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies (”BOGUS AGREEMENTS”) that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Nov 23, 2010, at 3:41 PM, Greg Ewing wrote: While it may be possible to work around these things with sufficient levels of metaclass hackery and black magic, at some point one has to consider whether new syntax might be the least worst option. The least worst option is to do nothing at all. That's better than creating a new little monster with its own nuances and limitations. We've gotten by well for almost two decades without this particular static language feature creeping into Python. For the most part, strings work well enough (see decimal.ROUND_UP for example). They are self-documenting and work well with the rest of the language. When a cluster of names cries out for its own namespace, the usual technique is to put the names in class (see the examples in the namedtuple docs for a way to make this a one-liner) or in a module (see opcode.py for example). For xor'able and or'able flags, sets of strings work well: flags = {'runnable', 'callable'} flags |= {'runnable', 'kissable'} if 'callable' in flags: . . . We have a hard enough time getting people to not program Java in Python. IMO, adding a new enumeration type would make this situation worse. Also, it adds weight to the language -- Python is not in needs of yet another fundamental construct. Raymond P.S. I do recognize that lots of people have written their own versions of Enum(), but I think they do it either out of habits formed from statically compiled languages that lack all of our namespace mechanisms or they do it because it is easy and fun to write (just like people seem to enjoy writing flatten() recipes more than they like actually using them). One other thought: With Py3.x, the language had its one chance to get smaller. Old-style classes were tossed, some built-ins vanished, and a few obsolete modules got nuked. It would be easy to have a let's add thingie x fest and lose those benefits. There are many devs who find that the language does not fit-in-their-heads anymore, so considerable restraint needs to be exercised before adding a new language feature that would soon permeate everyone's code base and add yet another thing that infrequent users have to learn before being able to read code. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] constant/enum type in stdlib
On Tue, Nov 23, 2010 at 9:35 PM, Raymond Hettinger raymond.hettin...@gmail.com wrote: The least worst option is to do nothing at all. For the standard library, I agree. There are enough variants that are needed/desired in different contexts, and there isn't a single clear winner. Nor is there any compelling reason to have a winner. I'm generally in favor of enums (or whatever you want to call them), and I'm in favor of importing support for the flavor you need, or just defining constants in whatever way makes sense for your library or application. I don't see any problems that aren't solved by that. -Fred -- Fred L. Drake, Jr. fdrake at acm.org A storm broke loose in my mind. --Albert Einstein ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com