Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
Why not defining new methods/changing the behaviour using a different metaclass? Victor Le 27 avr. 2013 05:12, Nikolaus Rath nikol...@rath.org a écrit : Steven D'Aprano st...@pearwood.info writes: On 26/04/13 13:22, Greg wrote: On 26/04/2013 3:12 p.m., Glenn Linderman wrote: On 4/25/2013 7:49 PM, Nick Coghlan wrote: You couldn't create an enum of callables, but that would be a seriously weird thing to do anyway But aren't all classes callable? An enum of classes would be seriously weird as well, I think. I don't think iscallable will work, since that descriptors like staticmethod and classmethod aren't callable. Nor are properties. I think a solution may be an explicit decorator that tells the metaclass not to skip the object into an enum value: class Insect(enum.Enum): ant = 1 bee = 2 @enum.skip @classmethod def spam(cls, args): pass In this case, wouldn't it be nicer to decorate those attributes that are meant to be enum values? I think having to use the class keyword to define something that really doesn't behave like an ordinary class is pretty confusing, and the following syntax would be a lot easier to understand at first sight: class Insect(enum.Enum): ant = enum.EnumValue(1) bee = enum.EnumValue(2) @classmethod def spam(cls, args): pass def ham(self, args): pass Obviously, EnumValue() would automatically assign a suitable number. Best, -Nikolaus -- »Time flies like an arrow, fruit flies like a Banana.« PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C ___ 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/victor.stinner%40gmail.com ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On Sat, Apr 27, 2013 at 7:41 AM, Guido van Rossum gu...@python.org wrote: On Fri, Apr 26, 2013 at 11:17 AM, Eli Bendersky eli...@gmail.com wrote: In contrast, personally I feel the current proposal in PEP 435 has an appeal from the POV of simplicity. It really is a very nice separation of concerns between enum values and Enum as a container of such values. It even allows significant customization (IntEnum, etc) which is pretty simple to grok. It would be a shame to lose these for the sake of making Python a bit more like Java. But it's not so much the like Java that matters to me. It's the realization that for the user who wants to define an enum type with some extra functionality, having a single class and putting the methods and the items in the same class is the simplest way to do it. The Java reference is just to point out that we're not exactly breaking new ground here. A common idiom in some other use cases (like ORMs) is to allow an inner class to customise behaviour beyond what the basic class syntax allows. It seems like that may be a good fit here, as a couple of simple changes should greatly simplify the process of tweaking the behaviour of the enum items, without adding more complexity to the implementation: 1. Change the name of __value_factory__ to something more concise like __enumitem__. 2. Make EnumItem and IntEnumItem public classes (Barry has already noted that the current naming the associated classes in flufl.enum and PEP 435 isn't quite right, since the intended terminology is enum for the class, enum item for the labelled values, and value for the raw unlabelled objects, but the class names are currently EnumValue and IntEnumValue). Then, if you want to add custom behaviour to your enum, you would be able to do use a nested class relatively cleanly: class MyEnum(Enum): itemA = 1 itemB = 2 class __enumitem__(EnumItem): def __init__(self, enum, value, name): if not name.startswith(item): raise ValueError(Item name {} doesn't start with 'item'.format(name)) super().__init__(enum, value, name) @property def letter(self): return self.name[4:] class MyExtendedEnum(MyEnum): # The custom __enumitem__ is inherited along with the original attributes itemC = 3 itemD = 4 Furthermore, rather than tweaking isinstance checks, it may make more sense to support containment testing for enums, such that you can write things like: assert MyEnum.itemA in MyEnum assert 1 not in MyEnum 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
[Python-Dev] Odp: PEP 435 -- Adding an Enum type to the Python standard library
Guido van Rossum wrote: we'd like to be able to define methods for the enum values, and the simplest way (for the user) to define methods for the enum values would be to allow def statements, possibly decorated, in the class. But now the implementation has to draw a somewhat murky line between which definitions in the class should be interpreted as enum value definitions, and which should be interpreted as method definitions. If we had access to the syntax used for the definition, this would be simple: assignments define items, def statements define methods. But at run time we only see the final object resulting from the definition, which may not even be callable in the case of certain decorators. I am still optimistic that we can come up with a rule that works well enough in practice (and the Zen rule to which I was referring was, of course, practicality beats purity). Maybe only names that do *not* start with underscore should be treated as enum value names; and those starting with underscore could be used e.g. to define methods etc.? Python has a long tradition of treating names differently depending of that feature. *j -- Sent from phone... ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
I've always found the nested class solution confusing when I had to use it in Django. It is a technical solution to a technical problem, but the resulting code is not very readable unless you have seen it a lot; it is a new, exceptional pattern. And as for using 'in' instead of 'isinstance' to check whether a value belongs to a given enum class, that, too, is a deviation from normal practice, which will require special cases in frameworks provide e.g. type checking. (As I mentioned before, any framework using argument annotations to indicate the expected type(s) for arguments would have to special-case the checks for enums.) Please let's try harder to come up with a way to separate enum value definitions from method definitions that works as expected in most common cases. I am willing to concede that it's hard to support things like class variables; maybe __private variables can be used for these; or the code can just use globals instead of class variables to hold per-class state. And __init__/__new__ probably shouldn't be overridden. But instance methods, class methods, static methods, properties, and other decorated methods should all work, as should special methods like __add__ or __getitem__. Hm... A lightbulb just went off. Objects representing both undecorated and decorated methods have a __get__() method, courtesy of the descriptor protocol. Maybe checking for that will work? It feels Pythonic to me: it uses a corner of the language that most people don't even know exists (*), but it produces the desired effect in almost all cases that matter, the pattern is simple to describe and easy to use without thinking about it, and for experts the rules are completely clear, uncomplicated, and free of heuristics, so it is possible to reason about corner cases. (*) Proof: even I didn't think of it until just now. :-) On Sat, Apr 27, 2013 at 6:17 AM, Nick Coghlan ncogh...@gmail.com wrote: On Sat, Apr 27, 2013 at 7:41 AM, Guido van Rossum gu...@python.org wrote: On Fri, Apr 26, 2013 at 11:17 AM, Eli Bendersky eli...@gmail.com wrote: In contrast, personally I feel the current proposal in PEP 435 has an appeal from the POV of simplicity. It really is a very nice separation of concerns between enum values and Enum as a container of such values. It even allows significant customization (IntEnum, etc) which is pretty simple to grok. It would be a shame to lose these for the sake of making Python a bit more like Java. But it's not so much the like Java that matters to me. It's the realization that for the user who wants to define an enum type with some extra functionality, having a single class and putting the methods and the items in the same class is the simplest way to do it. The Java reference is just to point out that we're not exactly breaking new ground here. A common idiom in some other use cases (like ORMs) is to allow an inner class to customise behaviour beyond what the basic class syntax allows. It seems like that may be a good fit here, as a couple of simple changes should greatly simplify the process of tweaking the behaviour of the enum items, without adding more complexity to the implementation: 1. Change the name of __value_factory__ to something more concise like __enumitem__. 2. Make EnumItem and IntEnumItem public classes (Barry has already noted that the current naming the associated classes in flufl.enum and PEP 435 isn't quite right, since the intended terminology is enum for the class, enum item for the labelled values, and value for the raw unlabelled objects, but the class names are currently EnumValue and IntEnumValue). Then, if you want to add custom behaviour to your enum, you would be able to do use a nested class relatively cleanly: class MyEnum(Enum): itemA = 1 itemB = 2 class __enumitem__(EnumItem): def __init__(self, enum, value, name): if not name.startswith(item): raise ValueError(Item name {} doesn't start with 'item'.format(name)) super().__init__(enum, value, name) @property def letter(self): return self.name[4:] class MyExtendedEnum(MyEnum): # The custom __enumitem__ is inherited along with the original attributes itemC = 3 itemD = 4 Furthermore, rather than tweaking isinstance checks, it may make more sense to support containment testing for enums, such that you can write things like: assert MyEnum.itemA in MyEnum assert 1 not in MyEnum Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia -- --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] PEP 435 -- Adding an Enum type to the Python standard library
On 04/26/2013 02:41 PM, Guido van Rossum wrote: I am still optimistic that we can come up with a rule that works well enough in practice (and the Zen rule to which I was referring was, of course, practicality beats purity). The rule I liked best is ignore callables, descriptors, and anything with leading trailing double underscores. Personally I'd modify that to simply anything with two leading underscores so you can have private variables. It seems Pythonic to me in that classes already treat all those things special. And if you want enums of any of those things you can instantiate insert them by hand after the class definition. Does that fail in an important way? //arry/ ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On Sun, Apr 28, 2013 at 2:11 AM, Larry Hastings la...@hastings.org wrote: On 04/26/2013 02:41 PM, Guido van Rossum wrote: I am still optimistic that we can come up with a rule that works well enough in practice (and the Zen rule to which I was referring was, of course, practicality beats purity). The rule I liked best is ignore callables, descriptors, and anything with leading trailing double underscores. Personally I'd modify that to simply anything with two leading underscores so you can have private variables. It seems Pythonic to me in that classes already treat all those things special. And if you want enums of any of those things you can instantiate insert them by hand after the class definition. Does that fail in an important way? Nope, those cover it. 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] PEP 435 -- Adding an Enum type to the Python standard library
On 04/27/2013 09:01 AM, Guido van Rossum wrote: Hm... A lightbulb just went off. Objects representing both undecorated and decorated methods have a __get__() method, courtesy of the descriptor protocol. Maybe checking for that will work? It feels Pythonic to me: it uses a corner of the language that most people don't even know exists (*), but it produces the desired effect in almost all cases that matter, the pattern is simple to describe and easy to use without thinking about it, and for experts the rules are completely clear, uncomplicated, and free of heuristics, so it is possible to reason about corner cases. While this will certainly work, it means you can't have class variables that happen to be the same type as the enum -- so no int in an IntEnum, for example. The solution I like best is the helper class (called, originally enough, enum), and only those items get transformed: class Planet(IntEnum): MERCURY = enum(1) VENUS = enum(2) EARTH = enum(3) rough_pi = 3 # not transformed -- ~Ethan~ ___ 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
[Python-Dev] Questions about Codon Alignment Proposal
Hi Eric and Peter, I'm preparing the proposal for the codon alignment project. Two things I may want to hear your advice. 1) In the biopython wiki page, you mentioned model selection in the Approach Goals. I'm not sure if there are any advantages to use codon alignment for model selection. Could you give me some references? Another thing is that model selection involves estimation of tree topology as well as branch lengthes and parameters across many substitution models. Will it be too computationally intensive for a python implementation? 2) You also mentioned the validation (testing for frame shift). Is there a test for frame shift? Or I can simply detect it by comparing amino acid sequences and nucleotide sequences. Best, Zheng Ruan___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On Sat, Apr 27, 2013 at 9:41 AM, Nick Coghlan ncogh...@gmail.com wrote: On Sun, Apr 28, 2013 at 2:11 AM, Larry Hastings la...@hastings.org wrote: On 04/26/2013 02:41 PM, Guido van Rossum wrote: I am still optimistic that we can come up with a rule that works well enough in practice (and the Zen rule to which I was referring was, of course, practicality beats purity). The rule I liked best is ignore callables, descriptors, and anything with leading trailing double underscores. Personally I'd modify that to simply anything with two leading underscores so you can have private variables. It seems Pythonic to me in that classes already treat all those things special. And if you want enums of any of those things you can instantiate insert them by hand after the class definition. Does that fail in an important way? Nope, those cover it. Great, sounds like a plan. The exception for callables may not even be needed -- the callables we care about (and some non-callables, like properties) are all descriptors. Or do we care about nested class definitions? (The reason I'm not keen on a general exemption for callables is that some 3rd party objects you wouldn't necessarily expect to be callable actually are.) I agree on a general exemption for __dunder__ names. The problem with exempting __private is that by the time the metaclass sees them, they've already been mangled to _classname__private. And I could just about imagine a use case for having a private value in an enum. -- --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] Questions about Codon Alignment Proposal
Sounds like this was accidentally CC'ed to python-dev. On Sat, Apr 27, 2013 at 10:23 AM, 阮铮 rz1...@foxmail.com wrote: Hi Eric and Peter, I'm preparing the proposal for the codon alignment project. Two things I may want to hear your advice. 1) In the biopython wiki page, you mentioned model selection in the Approach Goals. I'm not sure if there are any advantages to use codon alignment for model selection. Could you give me some references? Another thing is that model selection involves estimation of tree topology as well as branch lengthes and parameters across many substitution models. Will it be too computationally intensive for a python implementation? 2) You also mentioned the validation (testing for frame shift). Is there a test for frame shift? Or I can simply detect it by comparing amino acid sequences and nucleotide sequences. Best, Zheng Ruan ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On Sat, Apr 27, 2013 at 10:04 AM, Ethan Furman et...@stoneleaf.us wrote: While this will certainly work, it means you can't have class variables that happen to be the same type as the enum -- so no int in an IntEnum, for example. The solution I like best is the helper class (called, originally enough, enum), and only those items get transformed: class Planet(IntEnum): MERCURY = enum(1) VENUS = enum(2) EARTH = enum(3) rough_pi = 3 # not transformed If this means that the most plain vanilla enum definition still has to use the enum(i) notation, I'm against it. Why do you want rough_pi to be a class variable anyway? The whole point of an enum is that it's *not* a kitchen sink class. An enum for the planets will need other support code that doesn't live in the enum class -- it shouldn't be considered a general scope for miscellanea. (TBH, I think that using classes to scope variables is mostly misguided anyway -- the standard mechanism for scoping is the module.) -- --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
[Python-Dev] class name spaces inside an outer function
I filed bug http://bugs.python.org/issue17853 last night. If somebody could point me in the right direction (mainly which files to look in), I'd be happy to attempt a patch. -- ~Ethan~ ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On 27/04/13 12:51, Ethan Furman wrote: On 04/26/2013 07:29 PM, Glenn Linderman wrote: [...] class Color( Enum ): Enum.__enumerationItems__( red=1, green=2, blue=3, ) # other methods and assignments Or, if we go with the metaclass magic of re-using the class/type name (and who doesn't love metaclass magic??): class Color(Enum): red = Color(1) green = Color(2) blue = Color 3) look_ma_not_an_enum = 4 and from a later email: The solution I like best is the helper class (called, originally enough, enum), and only those items get transformed: class Planet(IntEnum): MERCURY = enum(1) VENUS = enum(2) EARTH = enum(3) rough_pi = 3 # not transformed I'm sorry, but all these suggestions are getting the API completely backwards by making the common case harder than the rare case. We're creating an Enum, right? So the *common case* is to populate it with enum values. 99% of the time, enumerated values will be all that we want from an enum. So that's the case that needs to be simple, not the rare case where you have a non enum value in an enum class. The common case (enum values in an Enum class) should be easy, and the rare cases (ordinary class-like attributes) possible. Explicit is better than implicit: if you want something to *not* be processed by the Enum metaclass, you have to explicitly mark it as special. Dunders excepted, because they *are* special enough to break the rules. Since dunders are reserved for Python, I'm happy with a rule that says that dunders cannot be set as enum values (at least not via the metaclass). Otherwise, everything inside an Enum class is treated as an enum value unless explicitly flagged as not. Here's a dirty hack that demonstrates what I'm talking about. class EnumValue: # Mock EnumValue class. def __new__(cls, name, obj): print(making enum {!s} from {!r}.format(name, obj)) return obj class MetaEnum(type): def __new__(meta, name, bases, namespace): cls = super().__new__(meta, name, bases, {}) for name, value in namespace.items(): if meta.isspecial(value): value = value.original elif not meta.isdunder(name): value = EnumValue(name, value) setattr(cls, name, value) return cls @staticmethod def isdunder(name): return name.startswith('__') and name.endswith('__') @staticmethod def isspecial(obj): return isinstance(obj, skip) class skip: def __init__(self, obj): self.original = obj class Example(metaclass=MetaEnum): red = 1 blue = 2 green = lambda: 'good lord, even functions can be enums!' def __init__(self, count=3): self.count = count food = skip('spam') @skip def spam(self): return self.count * self.food -- 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] PEP 435 -- Adding an Enum type to the Python standard library
On 04/27/2013 10:35 AM, Guido van Rossum wrote: On Sat, Apr 27, 2013 at 10:04 AM, Ethan Furman et...@stoneleaf.us wrote: While this will certainly work, it means you can't have class variables that happen to be the same type as the enum -- so no int in an IntEnum, for example. The solution I like best is the helper class (called, originally enough, enum), and only those items get transformed: class Planet(IntEnum): MERCURY = enum(1) VENUS = enum(2) EARTH = enum(3) rough_pi = 3 # not transformed If this means that the most plain vanilla enum definition still has to use the enum(i) notation, I'm against it. Why do you want rough_pi to be a class variable anyway? The whole point of an enum is that it's *not* a kitchen sink class. An enum for the planets will need other support code that doesn't live in the enum class -- it shouldn't be considered a general scope for miscellanea. (TBH, I think that using classes to scope variables is mostly misguided anyway -- the standard mechanism for scoping is the module.) The two primary use cases I see are the (1) quick give me some names to values so I can fiddle and experiment, and the (2) production code with nice docs and the whole shebang. For (1) I would just use the _make (or whatever it's called) to give me something; for (2) using 'enum()' so that a docstring can also be added (even encouraged ;) seems like a Good Thing. And no, I have no idea what rough_pi is doing there, besides being an example on an int that doesn't get transformed. ;) -- ~Ethan~ ___ 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] Questions about Codon Alignment Proposal
Hi Guido, Yes indeed, wrong list - I've forwarded this to the intended destination, biopython-dev, and we'll continue the discussion there: http://lists.open-bio.org/pipermail/biopython-dev/2013-April/010560.html (It is nice to see Python getting used in all sorts of Google Summer of Code projects though - and I'm sure we're all keen to try and welcome and encourage new students to the different open source communities.) Thanks, Peter On Sat, Apr 27, 2013 at 6:36 PM, Guido van Rossum gu...@python.org wrote: Sounds like this was accidentally CC'ed to python-dev. On Sat, Apr 27, 2013 at 10:23 AM, 阮铮 rz1...@foxmail.com wrote: Hi Eric and Peter, I'm preparing the proposal for the codon alignment project. Two things I may want to hear your advice. 1) In the biopython wiki page, you mentioned model selection in the Approach Goals. I'm not sure if there are any advantages to use codon alignment for model selection. Could you give me some references? Another thing is that model selection involves estimation of tree topology as well as branch lengthes and parameters across many substitution models. Will it be too computationally intensive for a python implementation? 2) You also mentioned the validation (testing for frame shift). Is there a test for frame shift? Or I can simply detect it by comparing amino acid sequences and nucleotide sequences. Best, Zheng Ruan ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On 04/27/2013 12:47 PM, Ethan Furman wrote: On 04/27/2013 11:45 AM, Steven D'Aprano wrote: On 27/04/13 12:51, Ethan Furman wrote: On 04/26/2013 07:29 PM, Glenn Linderman wrote: [...] class Color( Enum ): Enum.__enumerationItems__( red=1, green=2, blue=3, ) # other methods and assignments Or, if we go with the metaclass magic of re-using the class/type name (and who doesn't love metaclass magic??): class Color(Enum): red = Color(1) green = Color(2) blue = Color 3) look_ma_not_an_enum = 4 and from a later email: The solution I like best is the helper class (called, originally enough, enum), and only those items get transformed: class Planet(IntEnum): MERCURY = enum(1) VENUS = enum(2) EARTH = enum(3) rough_pi = 3 # not transformed I'm sorry, but all these suggestions are getting the API completely backwards by making the common case harder than the rare case. I should have made a better example. In production code, doc strings can be priceless, so encouraging them seems like a good idea: class Planet(IntEnum): MERCURY = enum(1, doc='closest planet to the sun (?)') VENUS = enum(2, doc='the one with two names') EARTH = enum(3, doc='home sweet home') random_value = 42 Of course, I think it would be even better if the name were 'Planet' instead of 'enum' as that would emphasize the fact that we are actually creating items of the enumeration inside the enumeration. Kind of a shorthand for: class Planet(IntEnum): def __init__(...): ... def blahblah(...): ... Planet.MERCURY = Planet(...) Planet.VENUS = Planet(...) Planet.EARTH = Planet(...) which is the way I've done it for other classes in a similar situation. We're creating an Enum, right? So the *common case* is to populate it with enum values. 99% of the time, enumerated values will be all that we want from an enum. So that's the case that needs to be simple, not the rare case where you have a non enum value in an enum class. The common case (enum values in an Enum class) should be easy, and the rare cases (ordinary class-like attributes) possible. Explicit is better than implicit: if you want something to *not* be processed by the Enum metaclass, you have to explicitly mark it as special. Dunders excepted, because they *are* special enough to break the rules. Since dunders are reserved for Python, I'm happy with a rule that says that dunders cannot be set as enum values (at least not via the metaclass). Otherwise, everything inside an Enum class is treated as an enum value unless explicitly flagged as not. While I agree that the common case should be simple, I also disagree that everything (especially functions) should easily be an enumerated value; the nice thing about being explicit as to which are the values (using 'enum' for example) is that it can also be used to capture functions in the rare case where that's what is desired. Just a quick followup: It seems to me that the *most* common case will be a simple name mapping, in which case one can do: Planet = Enum._make('Planet', 'MERCURY VENUS EARTH') and be done with it. -- ~Ethan~ ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On 04/27/2013 11:45 AM, Steven D'Aprano wrote: On 27/04/13 12:51, Ethan Furman wrote: On 04/26/2013 07:29 PM, Glenn Linderman wrote: [...] class Color( Enum ): Enum.__enumerationItems__( red=1, green=2, blue=3, ) # other methods and assignments Or, if we go with the metaclass magic of re-using the class/type name (and who doesn't love metaclass magic??): class Color(Enum): red = Color(1) green = Color(2) blue = Color 3) look_ma_not_an_enum = 4 and from a later email: The solution I like best is the helper class (called, originally enough, enum), and only those items get transformed: class Planet(IntEnum): MERCURY = enum(1) VENUS = enum(2) EARTH = enum(3) rough_pi = 3 # not transformed I'm sorry, but all these suggestions are getting the API completely backwards by making the common case harder than the rare case. I should have made a better example. In production code, doc strings can be priceless, so encouraging them seems like a good idea: class Planet(IntEnum): MERCURY = enum(1, doc='closest planet to the sun (?)') VENUS = enum(2, doc='the one with two names') EARTH = enum(3, doc='home sweet home') random_value = 42 Of course, I think it would be even better if the name were 'Planet' instead of 'enum' as that would emphasize the fact that we are actually creating items of the enumeration inside the enumeration. Kind of a shorthand for: class Planet(IntEnum): def __init__(...): ... def blahblah(...): ... Planet.MERCURY = Planet(...) Planet.VENUS = Planet(...) Planet.EARTH = Planet(...) which is the way I've done it for other classes in a similar situation. We're creating an Enum, right? So the *common case* is to populate it with enum values. 99% of the time, enumerated values will be all that we want from an enum. So that's the case that needs to be simple, not the rare case where you have a non enum value in an enum class. The common case (enum values in an Enum class) should be easy, and the rare cases (ordinary class-like attributes) possible. Explicit is better than implicit: if you want something to *not* be processed by the Enum metaclass, you have to explicitly mark it as special. Dunders excepted, because they *are* special enough to break the rules. Since dunders are reserved for Python, I'm happy with a rule that says that dunders cannot be set as enum values (at least not via the metaclass). Otherwise, everything inside an Enum class is treated as an enum value unless explicitly flagged as not. While I agree that the common case should be simple, I also disagree that everything (especially functions) should easily be an enumerated value; the nice thing about being explicit as to which are the values (using 'enum' for example) is that it can also be used to capture functions in the rare case where that's what is desired. -- ~Ethan~ ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On Sat, Apr 27, 2013 at 1:01 PM, Ethan Furman et...@stoneleaf.us wrote: It seems to me that the *most* common case will be a simple name mapping, in which case one can do: Planet = Enum._make('Planet', 'MERCURY VENUS EARTH') and be done with it. That looks horrible. -- --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] PEP 435 -- Adding an Enum type to the Python standard library
On 04/27/2013 02:57 PM, Guido van Rossum wrote: On Sat, Apr 27, 2013 at 1:01 PM, Ethan Furman et...@stoneleaf.us wrote: It seems to me that the *most* common case will be a simple name mapping, in which case one can do: Planet = Enum._make('Planet', 'MERCURY VENUS EARTH') and be done with it. That looks horrible. I believe that's one of the current methods in flufl.enum. -- ~Ethan~ ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 27, 2013, at 2:57 PM, Guido van Rossum wrote: On Sat, Apr 27, 2013 at 1:01 PM, Ethan Furman et...@stoneleaf.us wrote: It seems to me that the *most* common case will be a simple name mapping, in which case one can do: Planet = Enum._make('Planet', 'MERCURY VENUS EARTH') and be done with it. That looks horrible. Call me crazy, but might I suggest: class Planet(Enum, values='MERCURY VENUS EARTH'): Planets of the Solar System I've always wanted something similar for namedtuples, such as: class Point(NamedTuple, field_names='x y z'): Planet location with Sun as etc Especially when the common idiom for specifying namedtuples w/ docstrings looks similar but leaves a lot to be desired w/ the required duplication of the name: class Point(namedtuple('Point', 'x y z')): Planet location with Sun as etc (Raymond's even endorsed the former): http://bugs.python.org/msg111722 -- Philip Jenvey ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On 04/27/2013 04:07 PM, Philip Jenvey wrote: Call me crazy, but might I suggest: class Planet(Enum, values='MERCURY VENUS EARTH'): Planets of the Solar System Okay, you're crazy! ;) I must be too, 'cause I really like that suggestion. Works easily, simple metaclass (or simple addition to current metaclass). Very nice. -- ~Ethan~ ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On 04/27/2013 04:17 PM, Ethan Furman wrote: On 04/27/2013 04:07 PM, Philip Jenvey wrote: class Planet(Enum, values='MERCURY VENUS EARTH'): Planets of the Solar System I must be too, 'cause I really like that suggestion. Works easily, simple metaclass (or simple addition to current metaclass). Very nice. Having said that, what does it look like for a longer enum? class Planet( Enum, names=''' MERCURY VENUS EARTH MARS SATURN JUPITER URANUS PLUTO ''', ): '''Planets of the Solar System''' Not sure I like that. Ah well. -- ~Ethan~ ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
Steven D'Aprano st...@pearwood.info writes: I'm sorry, but all these suggestions are getting the API completely backwards by making the common case harder than the rare case. We're creating an Enum, right? So the *common case* is to populate it with enum values. 99% of the time, enumerated values will be all that we want from an enum. So that's the case that needs to be simple, not the rare case where you have a non enum value in an enum class. The common case (enum values in an Enum class) should be easy, and the rare cases (ordinary class-like attributes) possible. Explicit is better than implicit: if you want something to *not* be processed by the Enum metaclass, you have to explicitly mark it as special. Dunders excepted, because they *are* special enough to break the rules. Since dunders are reserved for Python, I'm happy with a rule that says that dunders cannot be set as enum values (at least not via the metaclass). Otherwise, everything inside an Enum class is treated as an enum value unless explicitly flagged as not. Here's a dirty hack that demonstrates what I'm talking about. [...] class Example(metaclass=MetaEnum): red = 1 blue = 2 green = lambda: 'good lord, even functions can be enums!' def __init__(self, count=3): self.count = count food = skip('spam') @skip def spam(self): return self.count * self.food However, without knowing that the MetaEnum metaclass will do some magic here, there's no way to know that there's anything special about red, blue and green. So I think there's actually a lot of implicit stuff happening here. In contrast, class Example(metaclass=MetaEnum): red = EnumValue(1) blue = EnumValue(2) green = EnumValue(lambda: 'good lord, even functions can be enums!') def __init__(self, count=3): self.count = count def spam(self): return self.count * self.food Makes it very clear that red, blue will not be attributes of type int, even if one has never heard of Enums or metaclasses before. I don't think this syntax is making the common case hard. By the same logic, you'd need to introduce C-style i++ postincrement because having just i += x makes the common case with x=1 hard as well. Best, -Nikolaus -- »Time flies like an arrow, fruit flies like a Banana.« PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C ___ 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] class name spaces inside an outer function
On Sat, Apr 27, 2013 at 2:27 PM, Ethan Furman et...@stoneleaf.us wrote: I filed bug http://bugs.python.org/issue17853 last night. If somebody could point me in the right direction (mainly which files to look in), I'd be happy to attempt a patch. Wow. I had no idea Python actually did this (override class-local references with ; I'd have expected your code to work. I was even more surprised to find that the same thing happens all the way back to Python 2.3. Guess I'm not nearly the wizard of abusing scope rules that I thought I was. ;-) About the only workaround I can see is to put Season = Season at the top of a class that uses this inside a function definition, or else to define a special name 'enum' instead and hope that nobody ever tries to define an enumeration inside a function with a local variable named 'enum'. ;-) ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On Sat, Apr 27, 2013 at 5:10 PM, Ethan Furman et...@stoneleaf.us wrote: class Planet( Enum, names=''' MERCURY VENUS EARTH MARS SATURN JUPITER URANUS PLUTO ''', ): '''Planets of the Solar System''' Not sure I like that. Ah well. The problem with this and similar proposals is that it puts things inside string quotes that belong outside them. -- --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] PEP 435 -- Adding an Enum type to the Python standard library
Guido van Rossum gu...@python.org writes: On Sat, Apr 27, 2013 at 10:04 AM, Ethan Furman et...@stoneleaf.us wrote: While this will certainly work, it means you can't have class variables that happen to be the same type as the enum -- so no int in an IntEnum, for example. The solution I like best is the helper class (called, originally enough, enum), and only those items get transformed: class Planet(IntEnum): MERCURY = enum(1) VENUS = enum(2) EARTH = enum(3) rough_pi = 3 # not transformed If this means that the most plain vanilla enum definition still has to use the enum(i) notation, I'm against it. I think this is actually a big advantage. It makes it obvious that something special is going on without having to know that IntEnum uses a special metaclass. Best, -Nikolaus -- »Time flies like an arrow, fruit flies like a Banana.« PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C ___ 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] class name spaces inside an outer function
On 28 Apr 2013 04:30, Ethan Furman et...@stoneleaf.us wrote: I filed bug http://bugs.python.org/issue17853 last night. If somebody could point me in the right direction (mainly which files to look in), I'd be happy to attempt a patch. Hmm, interesting challenge. A key part of the problem is that the 3.x compiler assumes there's no way to inject names it doesn't know about into code inside a function - we missed the fact that you could still do it with a nested class and a metaclass __prepare__ method. I suspect resolving it sensibly will require a new opcode that tries a local-only load and then falls back to loading from a cell rather than from a global/builtins lookup. Cheers, Nick. -- ~Ethan~ ___ 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/ncoghlan%40gmail.com ___ 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] class name spaces inside an outer function
2013/4/27 Nick Coghlan ncogh...@gmail.com: On 28 Apr 2013 04:30, Ethan Furman et...@stoneleaf.us wrote: I filed bug http://bugs.python.org/issue17853 last night. If somebody could point me in the right direction (mainly which files to look in), I'd be happy to attempt a patch. Hmm, interesting challenge. A key part of the problem is that the 3.x compiler assumes there's no way to inject names it doesn't know about into code inside a function - we missed the fact that you could still do it with a nested class and a metaclass __prepare__ method. That's not the problem. You can't inject names dynamically into a function scope with variables in a class scope, since nothing closes over them. I suspect resolving it sensibly will require a new opcode that tries a local-only load and then falls back to loading from a cell rather than from a global/builtins lookup. Yes. -- 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] class name spaces inside an outer function
PJ Eby wrote: On Sat, Apr 27, 2013 at 2:27 PM, Ethan Furman et...@stoneleaf.us wrote: I filed bug http://bugs.python.org/issue17853 last night. About the only workaround I can see is to put Season = Season at the top of a class that uses this inside a function definition, This whole business can be avoided by doing things differently in the first place. Instead of initialising the enum items by calling the class, just assign a tuple of args to the name and have the metaclass make the constructor call. class Planet(Enum): MERCURY = (3.303e+23, 2.4397e6) VENUS = (4.869e+24, 6.0518e6) EARTH = (5.976e+24, 6.37814e6) MARS= (6.421e+23, 3.3972e6) JUPITER = (1.9e+27, 7.1492e7) SATURN = (5.688e+26, 6.0268e7) URANUS = (8.686e+25, 2.5559e7) NEPTUNE = (1.024e+26, 2.4746e7) def __init__(self, mass, radius): self.mass = mass self.radius = radius I think that's better anyway, since it avoids aggravated violation of DRY by repeating the class name umpteen times. -- 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] PEP 435 -- Adding an Enum type to the Python standard library
Guido van Rossum wrote: And __init__/__new__ probably shouldn't be overridden. Why shouldn't __init__ be overridden? It's the obvious way to support Java-style enum-items-with-attributes. -- 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] class name spaces inside an outer function
On 04/27/2013 07:01 PM, Greg Ewing wrote: PJ Eby wrote: On Sat, Apr 27, 2013 at 2:27 PM, Ethan Furman et...@stoneleaf.us wrote: I filed bug http://bugs.python.org/issue17853 last night. About the only workaround I can see is to put Season = Season at the top of a class that uses this inside a function definition, This whole business can be avoided by doing things differently in the first place. Instead of initialising the enum items by calling the class, just assign a tuple of args to the name and have the metaclass make the constructor call. class Planet(Enum): MERCURY = (3.303e+23, 2.4397e6) VENUS = (4.869e+24, 6.0518e6) EARTH = (5.976e+24, 6.37814e6) MARS= (6.421e+23, 3.3972e6) JUPITER = (1.9e+27, 7.1492e7) SATURN = (5.688e+26, 6.0268e7) URANUS = (8.686e+25, 2.5559e7) NEPTUNE = (1.024e+26, 2.4746e7) def __init__(self, mass, radius): self.mass = mass self.radius = radius I think that's better anyway, since it avoids aggravated violation of DRY by repeating the class name umpteen times. You certainly have a point about DRY, and generally I agree with you, but given the nature of Enums I can see a little extra RY being useful. Regardless of the outcome for Enums, I can see another metaclass doing the same kind of thing and having it work just fine until an unsuspecting soul tries to reuse an inserted name further down the function and suddenly the whole thing blows up on him. Now, I'll grant you it's not like a seg fault, but it would be nice if Python followed its own lookup rules. -- ~Ethan~ ___ 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] PEP 435 -- Adding an Enum type to the Python standard library
On 04/27/2013 07:12 PM, Greg Ewing wrote: Guido van Rossum wrote: And __init__/__new__ probably shouldn't be overridden. Why shouldn't __init__ be overridden? It's the obvious way to support Java-style enum-items-with-attributes. Overriding __init__ is a PITA because __init__ is also called when you do Planet(3) # get EARTH and __init__ was expecting a gravitational constant and radius (or something like that). A couple ways around that: 1) have the metaclass store the args somewhere special (e.g. _args), have __init__ look like `def __init__(self, value=None)`, and have the body treat _args as if it were *args 2) have a `_init` that the metaclass calls with the args instead of __init__ -- ~Ethan~ ___ 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] [Python-checkins] cpython (3.3): Issue #17357: Use more stern wording for
This actually should have been for issue #17330, but I had the wrong bug open when I copy-and-pasted the number. On Sat, Apr 27, 2013 at 11:21 PM, brett.cannon python-check...@python.org wrote: http://hg.python.org/cpython/rev/75e32a0bfd74 changeset: 83525:75e32a0bfd74 branch: 3.3 parent: 83517:4b4ed1e11fd0 user:Brett Cannon br...@python.org date:Sat Apr 27 23:20:32 2013 -0400 summary: Issue #17357: Use more stern wording for importlib.invalidate_caches(). files: Doc/library/importlib.rst | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -103,9 +103,9 @@ Invalidate the internal caches of finders stored at :data:`sys.meta_path`. If a finder implements ``invalidate_caches()`` then it - will be called to perform the invalidation. This function may be needed if - some modules are installed while your program is running and you expect the - program to notice the changes. + will be called to perform the invalidation. This function should be called + if any modules are created/installed while your program is running to + guarantee all finders will notice the new module's existence. .. versionadded:: 3.3 @@ -182,7 +182,7 @@ .. versionadded:: 3.3 - .. method:: find_loader(fullname): + .. method:: find_loader(fullname) An abstract method for finding a :term:`loader` for the specified module. Returns a 2-tuple of ``(loader, portion)`` where ``portion`` @@ -194,7 +194,7 @@ the empty list then no loader or location for a namespace package were found (i.e. failure to find anything for the module). - .. method:: find_module(fullname): + .. method:: find_module(fullname) A concrete implementation of :meth:`Finder.find_module` which is equivalent to ``self.find_loader(fullname)[0]``. -- Repository URL: http://hg.python.org/cpython ___ Python-checkins mailing list python-check...@python.org http://mail.python.org/mailman/listinfo/python-checkins ___ 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] class name spaces inside an outer function
On Sun, Apr 28, 2013 at 11:38 AM, Benjamin Peterson benja...@python.org wrote: 2013/4/27 Nick Coghlan ncogh...@gmail.com: On 28 Apr 2013 04:30, Ethan Furman et...@stoneleaf.us wrote: I filed bug http://bugs.python.org/issue17853 last night. If somebody could point me in the right direction (mainly which files to look in), I'd be happy to attempt a patch. Hmm, interesting challenge. A key part of the problem is that the 3.x compiler assumes there's no way to inject names it doesn't know about into code inside a function - we missed the fact that you could still do it with a nested class and a metaclass __prepare__ method. That's not the problem. You can't inject names dynamically into a function scope with variables in a class scope, since nothing closes over them. Yeah, what I wrote didn't quite capture what I meant: - in Python 2.x, using LOAD_DEREF when a nested class body references a lexically scoped name is correct - in Python 3.x, it is no longer correct, because __prepare__ may inject additional names that the compiler doesn't know about Previously, the compiler new just as much about the nested class namespaces as it did about the function locals. 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] class name spaces inside an outer function
2013/4/27 Nick Coghlan ncogh...@gmail.com: On Sun, Apr 28, 2013 at 11:38 AM, Benjamin Peterson benja...@python.org wrote: 2013/4/27 Nick Coghlan ncogh...@gmail.com: On 28 Apr 2013 04:30, Ethan Furman et...@stoneleaf.us wrote: I filed bug http://bugs.python.org/issue17853 last night. If somebody could point me in the right direction (mainly which files to look in), I'd be happy to attempt a patch. Hmm, interesting challenge. A key part of the problem is that the 3.x compiler assumes there's no way to inject names it doesn't know about into code inside a function - we missed the fact that you could still do it with a nested class and a metaclass __prepare__ method. That's not the problem. You can't inject names dynamically into a function scope with variables in a class scope, since nothing closes over them. Yeah, what I wrote didn't quite capture what I meant: - in Python 2.x, using LOAD_DEREF when a nested class body references a lexically scoped name is correct - in Python 3.x, it is no longer correct, because __prepare__ may inject additional names that the compiler doesn't know about You could still get the same bug in Python 2 by messing with locals() in a class within a function. -- 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] PEP 435 -- Adding an Enum type to the Python standard library
Ethan Furman wrote: Overriding __init__ is a PITA because __init__ is also called when you do Planet(3) # get EARTH and __init__ was expecting a gravitational constant and radius (or something like that). A couple ways around that: 1) have the metaclass store the args somewhere special 2) have a `_init` that the metaclass calls with the args instead of __init__ I don't much like either of those. It would be much nicer if one could just write an ordinary __init__ method and have it work as expected. It's possible to make it work, I think. The __call__ method of the metaclass is going to have to do something special anyway, so that Planet(3) can look up and return an existing instance instead of making a new one. And if it doesn't make a new instance, it's not going to call the __init__ method. -- 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] class name spaces inside an outer function
On Saturday, April 27, 2013, Greg Ewing wrote: This whole business can be avoided by doing things differently in the first place. Instead of initialising the enum items by calling the class, just assign a tuple of args to the name and have the metaclass make the constructor call. class Planet(Enum): MERCURY = (3.303e+23, 2.4397e6) VENUS = (4.869e+24, 6.0518e6) EARTH = (5.976e+24, 6.37814e6) MARS= (6.421e+23, 3.3972e6) JUPITER = (1.9e+27, 7.1492e7) SATURN = (5.688e+26, 6.0268e7) URANUS = (8.686e+25, 2.5559e7) NEPTUNE = (1.024e+26, 2.4746e7) def __init__(self, mass, radius): self.mass = mass self.radius = radius I think that's better anyway, since it avoids aggravated violation of DRY by repeating the class name umpteen times. If you want something like this, doyou really have to inherit from Enum? -- --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