子类Python枚举中的重写方法

子类Python枚举中的重写方法,python,python-3.x,enums,Python,Python 3.x,Enums,从子类化枚举开始,允许执行以下操作: >>> class Foo(Enum): ... def some_behavior(self): ... pass ... >>> class Bar(Foo): ... happy = 1 ... sad = 2 ... 假设我想以不同的方式为happy和sad枚举定义一些行为 有没有更好的方法可以做到这一点 >>> class Bar(Foo): ... happy = 1

从子类化枚举开始,允许执行以下操作:

>>> class Foo(Enum):
...   def some_behavior(self):
...     pass
...
>>> class Bar(Foo):
...   happy = 1
...   sad = 2
...
假设我想以不同的方式为
happy
sad
枚举定义
一些行为

有没有更好的方法可以做到这一点

>>> class Bar(Foo):
...   happy = 1
...   sad = 2
...   def some_behavior(self):
...       if self is Bar.happy:
...           # happy behavior
...       elif self is Bar.sad:
...           # sad behavior
我觉得那很笨重

没有

我的意思是,你也许可以这样做:

def some_behavior(self):
    return {Bar.happy: some_function
            Bar.sad: some_other_function}[self](arguments?)
def some_behavior(self):
    custom_thing = {Bar.happy: some_function
                    Bar.sad: some_other_function}[self]
    # do something which is the same for both
    custom_thing()
    # do something else the same for both
class Foo(Enum):
    happy = 1
    sad = 2

def happy_behavior():  # No self argument!
    self = Foo.happy  # only if you need self
    ...

def sad_behavior():
    self = Foo.sad
    ...

Foo.happy.some_behavior = happy_behavior
Foo.sad.some_behavior = sad_behavior
或者像这样:

def some_behavior(self):
    return {Bar.happy: some_function
            Bar.sad: some_other_function}[self](arguments?)
def some_behavior(self):
    custom_thing = {Bar.happy: some_function
                    Bar.sad: some_other_function}[self]
    # do something which is the same for both
    custom_thing()
    # do something else the same for both
class Foo(Enum):
    happy = 1
    sad = 2

def happy_behavior():  # No self argument!
    self = Foo.happy  # only if you need self
    ...

def sad_behavior():
    self = Foo.sad
    ...

Foo.happy.some_behavior = happy_behavior
Foo.sad.some_behavior = sad_behavior
但是,除非已经存在一些函数,否则这可能不会比您现在拥有的更好(尽管我想您可能能够保存一两级缩进)。您可以在这里使用lambdas,但它很快就会变得难看,我不推荐使用它,除非是在最简单的情况下(通常可以处理)

如评论中所述,您可以执行以下操作:

def some_behavior(self):
    return {Bar.happy: some_function
            Bar.sad: some_other_function}[self](arguments?)
def some_behavior(self):
    custom_thing = {Bar.happy: some_function
                    Bar.sad: some_other_function}[self]
    # do something which is the same for both
    custom_thing()
    # do something else the same for both
class Foo(Enum):
    happy = 1
    sad = 2

def happy_behavior():  # No self argument!
    self = Foo.happy  # only if you need self
    ...

def sad_behavior():
    self = Foo.sad
    ...

Foo.happy.some_behavior = happy_behavior
Foo.sad.some_behavior = sad_behavior
在我看来,这相当难看,但它应该在所有合理的情况下都有效,包括像
Foo(1).some\u behavior()
Foo['sad'].some\u behavior()
这样的表达式。但是,它可能会混淆静态类型检查器和/或过梁。

是的,有1个

诀窍在于覆盖
\uuuu getattribute\uuuu
,这会拦截所有名称查找,并且非常危险2:

然后编写最后的
枚举

class Bar(Foo):

    #
    # default methods
    #
    def some_behavior(self):
        return self.name + ' is neutral'

    def likes_to(self):
        return 'likes to sit'

    #
    # members
    #
    @member
    class happy:
        # overridden methods
        def some_behavior(self):
            return self.name + ' is happy'
        def likes_to(self):
            return 'likes to dance'

    @member
    class sad:
        # overridden method
        def some_behavior(self):
            return self.name + ' is sad'

    @member
    class okay:
        # uses default methods
        pass
在使用中:

>>> list(Bar)
[<Bar.happy>, <Bar.sad>, <Bar.okay>]

>>> Bar.happy.some_behavior()
'happy is happy'

>>> Bar.happy.likes_to()
'likes to dance'

>>> Bar.sad.some_behavior()
'sad is sad'

>>> Bar.sad.likes_to()
'likes to sit'

>>> Bar.okay.some_behavior()
'okay is neutral'

>>> Bar.okay.likes_to()
'likes to sit'
>>列表(条形图)
[, ]
>>>酒吧。快乐。一些行为()
“快乐就是快乐”
>>>酒吧。快乐。喜欢
“喜欢跳舞”
>>>酒吧。悲伤。一些行为()
“悲伤就是悲伤”
>>>酒吧。悲伤。喜欢
“喜欢坐”
>>>好吧,一些行为
“好的,是中立的”
>>>好吧,我喜欢
“喜欢坐”

1完全不惯用

2跳过
\uuuuu getattribute\uuuuuu
是危险的,因为它控制属性的处理方式——例如,描述符魔术在
对象中实现。这里的任何错误都可能导致难以调试的问题



披露:我是、和库的作者。

测试枚举身份的标准方法是使用
is
(例如
self is Bar.happy
)。你不使用它有什么原因吗?你是对的。从长远来看,Lambdas不会有什么好处。一些类似Javascript的语法:
happy.Some_behavior=def(){#dohappy stuff}
,在这里会很有用,它会退化为Python,除了lambdas之外没有匿名函数。实际上,您可以手动分配这样的函数,但这不是惯用的IMHO。所有Python函数都是一流的,不仅仅是lambdas。