Python 在没有实例的类对象上设置魔术方法?
假设我有一个简单的对象:Python 在没有实例的类对象上设置魔术方法?,python,Python,假设我有一个简单的对象: class Providers: Apple = "Apple" Banana = "Banana" Cherries = "Seedless Cherries" 我希望能够在提供者中执行类似于“Apple”的。,我相信这需要我设置两个神奇的方法,\uuuu len\uuu和\uuu getitem\uuuu 我试了一些简单的方法 @classmethod def __len__(cls): return 3 但是当我运行len(Pr
class Providers:
Apple = "Apple"
Banana = "Banana"
Cherries = "Seedless Cherries"
我希望能够在提供者中执行类似于“Apple”的。
,我相信这需要我设置两个神奇的方法,\uuuu len\uuu
和\uuu getitem\uuuu
我试了一些简单的方法
@classmethod
def __len__(cls):
return 3
但是当我运行len(Providers)
时,我得到TypeError:type'type'的对象没有len()
但是提供程序。\uu len\uuu()
返回3
如何在不实例化类的情况下获取类的len
?或者它们是否需要始终使用\uu init\uuu
和self.Apple='Apple'进行实例化?
使用元类:
class FooMeta(type):
def __len__(self):
return 10
class Foo(metaclass=FooMeta):
pass
print(len(Foo)) # 10
这是因为类实际上是对象,也就是说,它们是元类的实例。您需要使用
metclass
,因为当您使用len(提供者)
时,就像您使用type(提供者)
就你而言:
type(Providers) == <class 'type'> # no __len__ method here
这是python解释器处理dunder(魔法方法)方法的方式:
type(SomeObject)。\udunder\uuuuuuuuuuuuuuuuuuuoSomeObject)
如果您已经创建了一个类对象,如果您想在类对象中实现这些方法,那么您需要在类对象的类中,即在元类中实现它。或者,更合理地说,不要试图使用像容器这样的类。祝贺你,你已经重新发明了。这是有道理的。我在Airflow对遗嘱执行人的定义中看到了类似的代码:我认为这是一个很好的实践。我来看看enum。@pedram看起来他们并不像您的用例那样试图使用那个类,您似乎想要一个简单的记录/容器。这看起来像是命名间隔常量/枚举,比如classyeah,但这完全是一个过度工程化的解决方案,解决了一个本来就不应该存在的问题我同意,他们正确的方法是扩展容器类,通常来说,我更喜欢组合而不是继承,特别是在这种情况下,它不是任何容器类的自然扩展。OP似乎几乎想要一个枚举,但这只是我的猜测。我更喜欢FP而不是OOP。组合会减少代码的耦合,但我认为元类太令人兴奋了,需要展示出来。这是一个元类使用不当的好例子,但仍然是一个好例子。我只是想验证传入的数据是否与提供者定义的常量之一相匹配。我想我可以做一些类似于的事情,比如在提供者中使用var.\uu dict\uu.values()
,但这看起来很难看。@Martijn Pieters的一个很好的解释是: