gpt4 book ai didi

python - 重写类的 __contains__ 方法

转载 作者:太空狗 更新时间:2023-10-29 18:23:31 25 4
gpt4 key购买 nike

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

class Spam(Enum):
k = 3
EGGS = 0
HAM = 1
BAKEDBEANS = 2

现在我想测试某个常量是否是特定 Enum 派生类的有效选择,语法如下:

if (x in Foo):
print("seems legit")

因此,我尝试创建一个“枚举”基类,在其中重写 __contains__ 方法,如下所示:

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

为什么?我能以某种方式获得我想要的语法糖吗?

最佳答案

Why that?

当你使用像 a in Foo 这样的特殊语法时,__contains__ 方法会根据 Foo 的类型进行查找。但是,您的 __contains__ 实现存在于 Foo 本身,而不是它的类型。 Foo 的类型是 type,它没有实现这个(或迭代),因此是错误的。

如果您实例化一个对象,然后创建它之后,将 __contains__ 函数添加到实例变量,则会发生同样的情况。该函数不会被调用:

>>> 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

Can I somehow get the syntactic sugar I want?

是的。如上所述,该方法是根据 Foo 的类型查找的。类的类型称为 metaclass ,因此您需要一个实现 __contains__ 的新元类。

试试这个:

class MetaEnum(type):
def __contains__(cls, x):
return x in range(cls.k)

如您所见,元类上的方法将元类实例——类——作为它们的第一个参数。这应该是有道理的。它与类方法非常相似,只是该方法存在于元类而非类中。

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

class BaseEnum(metaclass=MetaEnum):
pass

class MyEnum(BaseEnum):
k = 3

print(1 in MyEnum) # True

关于python - 重写类的 __contains__ 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10445819/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com