Python 重写包含类的方法
我需要在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: """
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