Python 重写包含类的方法

Python 重写包含类的方法,python,python-3.x,metaclass,Python,Python 3.x,Metaclass,我需要在Python中模拟枚举,并通过编写如下类来实现: class Spam(Enum): k = 3 EGGS = 0 HAM = 1 BAKEDBEANS = 2 现在,我想用以下语法测试某个常量是否是特定枚举派生类的有效选项: if (x in Foo): print("seems legit") 因此,我尝试创建一个“Enum”基类,在其中重写\uuuuu contains\uuuu方法,如下所示: class Enum: """

我需要在Python中模拟枚举,并通过编写如下类来实现:

class Spam(Enum):
    k = 3
    EGGS = 0
    HAM = 1
    BAKEDBEANS = 2
现在,我想用以下语法测试某个常量是否是特定枚举派生类的有效选项:

if (x in Foo):
    print("seems legit")
因此,我尝试创建一个“Enum”基类,在其中重写
\uuuuu contains\uuuu
方法,如下所示:

class Enum:
    """
    Simulates an enum.
    """

    k = 0 # overwrite in subclass with number of constants

    @classmethod
    def __contains__(cls, x):
        """
        Test for valid enum constant x:
            x in Enum
        """
        return (x in range(cls.k))
但是,在类上使用
in
关键字(如上面的示例)时,我得到错误:

TypeError: argument of type 'type' is not iterable
为什么?我能得到我想要的语法糖吗

为什么

当您在Foo中使用像
a这样的特殊语法时,将在
Foo
的类型上查找
\uuuuuuuuuuuuuuuuuuuuuuuu
方法。但是,您的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
实现存在于
Foo
本身,而不是它的类型上
Foo
的类型是
type
,它没有实现此(或迭代),因此会出现错误

如果实例化一个对象,然后在创建该对象后,将
\uuuuu contains\uuuu
函数添加到实例变量,则会出现相同的情况。不会调用该函数:

>>> class Empty: pass
... 
>>> x = Empty()
>>> x.__contains__ = lambda: True
>>> 1 in x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument of type 'Empty' is not iterable
如您所见,元类上的方法将元类实例(类)作为其第一个参数。这应该是有道理的。它与classmethod非常相似,只是该方法存在于元类而不是类上

从具有自定义元类的类继承也会继承该元类,因此您可以像这样创建基类:

class BaseEnum(metaclass=MetaEnum):
    pass

class MyEnum(BaseEnum):
    k = 3

print(1 in MyEnum) # True

啊,我对元类的存在有一个模糊的想法,但我从来没有自己的用例。这很好,谢谢。8年后,这个美妙的答案让我在将一些包切换到Python 3.8时遇到了一个问题。我想,如果其他人在这里遇到类似的问题,那么我最终得到了什么,这对其他人来说是很有用的。我认为,一个澄清的注释,该代码可以很好地用于:if x in Foo():print(‘似乎合法’)将使问题和答案更容易理解。因为类型(Foo())是Foo,而类型(Foo)是元类。
class BaseEnum(metaclass=MetaEnum):
    pass

class MyEnum(BaseEnum):
    k = 3

print(1 in MyEnum) # True