On 29 Apr 2013 07:32, "Antoine Pitrou" <soli...@pitrou.net> wrote:
>
> On Sun, 28 Apr 2013 13:02:11 -0700
> Guido van Rossum <gu...@python.org> wrote:
> >
> > > Â - for the above two, how should they be included/excluded?
> >
> > IMO Everything should be enumerated except
> > (a) things with a __get__() method (i.e. descriptors)
> > (b) __dunder__ names
>
> I think it would be nice to define regular methods on enums.
Functions are descriptors, so this rule already covers ordinary methods. The slight concern I have with making the duck typed exclusion only descriptors (rather than descriptors and callables) is that it means things like functools.partial objects will be treated as enum values rather than as static methods. OTOH, explicitly wrapping such callables in staticmethod should still work, so the simpler rule is probably better.
Cheers,
Nick.
>
> Regards
>
> Antoine.
>
>
> _______________________________________________
> Python-Dev mailing list
> Pytho...@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: http://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com
I have also suggested that that the enum package provide a decorator
which can be used to explicitly flag values to *not* be turned into
enum values. See here:
http://mail.python.org/pipermail/python-dev/2013-April/125641.html
Even if the Enum class doesn't support this feature, I ask that it be
written in such a way that a subclass could add it (i.e. please expose
a public method for deciding what to exclude).
(2a. We could also allow Color('red') is Color.red, but that could be
confusing, and we can already do that with getattr(Color, 'red'), and
bool('False') doesn't return False anyway, so let's not do that.)
class Color(Enum):
red = 'white'
white = 'blue'
blue = 'red'
although that would no doubt drive the programmers batty anyway... but there may be instances where code is generated that could produce something ambiguous, even though this example is atrocious.
Enums are the same: they could return brand new instances every time, and programs using `==` to compare will keep on working. Â That they don't is an implementation detail.
Example enumeration:
class Seasons(Enum):
  SPRING = 1
  SUMMER = 2
  AUTUMN = 3
  WINTER = 4
  days_in_year = 365
  @property
  def avg_temp(self):
    return (75, 92, 66, 33)[int(self)+1] # enums are 1-based
Definite Issues:
 - should enum items be of the type of the Enum class? (i.e. type(SPRING) is Seasons)
 - should an enum item be selectable via __call__ instead of __getitem__ (i.e. Seasons(3) is AUTUMN)
 - should days_in_year be enumerated?
 - should avg_temp be enumerated?
 - for the above two, how should they be included/excluded?
flufl.enum disallows this:
class Color(Enum):
 red = 1
 blue = 2
 green = 1 # oops!
Has it been decided that this is now allowed? If this is indeed the case, then Color(1) is a problem. The options are:
A. Return either Color.red or Color.green
B. Throwing an error
Do we have a decision on this? Personally I think the latter is better; the former is error prone and doesn't seem to be useful too often.
Eli [trying to tie loose ends for updating the PEP].
class Color(Enum):
 red = 1
 blue = 2
Color.green = Color.red
On 30/04/13 02:42, Guido van Rossum wrote:
On Mon, Apr 29, 2013 at 6:51 AM, Eli Bendersky <eli...@gmail.com> wrote:
I don't feel strongly about allowing ()-lookup in addition to []-lookup, but
in this paragraph the issue of multiple definitions has sneaked in :-)
flufl.enum disallows this:
class Color(Enum):
  red = 1
  blue = 2
  green = 1 # oops!
Has it been decided that this is now allowed?
I don't recall if it was decided. I think it should be possible to
create aliases like this. The main thing I care about is that
Color.green == Color.red.
I believe that Barry had decided that it should be prohibited. I objected, and Nick pointed out that although declaring two enums with the same value inside the class is prohibited, aliases are supported by adding them from the outside:
class Color(Enum):
   red = 1
   blue = 2
Color.green = Color.red
which satisfies me.
class Color(Enum):
   red = 1
   blue = 2
Color.green = Color(1)
class Color(Enum):
   red = 1
   blue = 2
   green = 1
On 4/29/2013 8:24 AM, Eli Bendersky wrote:My only concern is that whatever you do does not break transitivity of ==. Aside from that, I will be happy with whatever you end up with and use it as appropriate.
Thanks for the summary. One issue I don't see addressed here is
int-compatibility. Am I correct to assume that nothing changes w.r.t.
that, and that an IntEnum subclass of Enum will be provided which is
isinstance(integer)? Does that become straightforward by nature of enum
values being the type of their enumerations?
On Apr 28, 2013, at 07:46 PM, Ethan Furman wrote:and similarly, Enum behavior /should be/ (in my opinion ;) Season.AUTUMN is Season('AUTUMN') is Season(3)I think you'll have a problem with this. flufl.enum did this, but it has an inherent conflict, which is why we removed the getattr-like behavior. class Things(Enum): foo = 'bar' bar = 'foo' What does Things('foo') return? Note that it doesn't matter if that's spelled Things['foo']. Whether it's defined as lookup or instance "creation", you should only map values to items, and not attribute names to items, and definitely not both. Let getattr() do attribute name lookup just like normal.
On 04/30/2013 11:18 PM, Barry Warsaw wrote:
On Apr 28, 2013, at 11:50 PM, Ethan Furman wrote:
But as soon as:
  type(Color.red) is Color         # True
  type(MoreColor.red) is MoreColor # True
then:
   Color.red is MoreColor.red # must be False, no?
If that last statement can still be True, I'd love it if someone showed me
how.
class Foo:
    a = object()
    b = object()
class Bar(Foo):
    c = object()
TrueFoo.a is Bar.a
Wow. I think I'm blushing from embarrassment.
Thank you for answering my question, Barry.
On May 02, 2013, at 08:42 AM, Larry Hastings wrote:It's a moot point now given Guido's pronouncement.
>So, for the second time: How can Color.red and MoreColor.red be the same
>object when they are of different types?
>>> class MoreColor(Color): ... pink = 17 ... TypeError: Cannot subclass enumerations
But this is allowed:
>>> class Foo(Enum): ... def some_behavior(self): ... pass ... >>> class Bar(Foo): ... happy = 1 ... sad = 2 ...
Eli
On 05/02/2013 04:45 PM, Greg Ewing wrote:I like it, thanks!
Eli Bendersky wrote:
TypeError: Cannot subclass enumerations
This message might be better phrased as "cannot extend
enumerations", since we're still allowing subclassing
prior to defining members.
Barry Warsaw wrote:It's not a problem that getattr() has this behaviour.
I still don't get it why this is an issue though, or at least why this is
different than any other getattr on any other class,
What I'm questioning is the idea that getattr() should
be the only provided way of doing a name->enum lookup,
because that will require everyone to do extra checks
to ensure safety.
The only reason to use enums at all is to improve logging and error messages. Thus, designing the API and behaviour of an enum type is mostly a matter of asking "What mistakes are developers likely to make?" and "How can the enum design help guide them towards a suitable solution?". The answers are a combination of API design and providing appropriate details in error messages.
If a developer doesn't care about those two questions then they would just use the raw underlying values.
Cheers,
Nick.
>
> Eli
>
>
>
>
> _______________________________________________
> Python-Dev mailing list
> Pytho...@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: http://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com
>
On 4 May 2013 09:34, "Guido van Rossum" <gu...@python.org> wrote:
>
> On Fri, May 3, 2013 at 4:08 PM, Greg Ewing <greg....@canterbury.ac.nz> wrote:
> > Guido van Rossum wrote:
> >>
> >> I haven't seen code in the style that
> >> Greg proposes in decades,
>
> > What style are you talking about here?
>
> Code that wants to validate a string the user typed as input. Web
> forms just don't work that way. (Command-line flags are a special
> case, and there are a slew of specialized parsers for that case.)
And for code that really needs it, it is straightforward to use dir(MyEnum) and isinstance(obj, MyEnum) to get an exact mapping of names to values that also accounts for aliases.
Cheers,
Nick.
>
> --
> --Guido van Rossum (python.org/~guido)
> _______________________________________________
> Python-Dev mailing list
> Pytho...@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: http://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com
On 4 May 2013 07:42, "Nick Coghlan" <ncog...@gmail.com> wrote:
> 2. We restore __getitem__ on EnumMetaclass *solely* for member lookup
> by name (the "getmember" functionality above). This would leave
> __call__ used for the reverse lookup (value to member and hence name)
> and __getitem__ for the forward lookup (name to member and hence
> value) (Note: given Ethan's comments about his current implementation,
> I believe this actually fits nicely with the way
> EnumMetaclass.__getattr__ is already implemented)
This has the advantage of leaving one obvious way to do the 'reverse' lookup (namely __call__), rather than two redundant alternatives.
Cheers,
Phil