有没有办法将__len__或__eq__等方法实现为类方法?
在Python中,实现__len__(self)
这个方法其实很简单,这样就能处理像len(inst)
这样的调用:
class A(object):
def __len__(self):
return 7
a = A()
len(a) # gives us 7
而且你可以定义很多类似的方法,比如__eq__
、__str__
、__repr__
等等。我知道Python中的类也是对象。
我想问的是:我能否以某种方式定义,比如__len__
,让下面的代码能够正常工作:
len(A) # makes sense and gives some predictable result
4 个回答
我不太明白语法具体有多重要,不过如果你想要一个简单的实现方法,可以用普通的 len(self) 来返回实例的长度,但在你的实现中让它返回一个所有实例共享的类变量:
class A:
my_length = 5
def __len__(self):
return self.my_length
然后你可以这样调用它:
len(A()) #returns 5
显然,这样会创建一个你类的临时实例,但长度这个概念只对类的实例有意义,而不太适合用在类本身(也就是一个类型对象)上。
修改元类听起来是个很糟糕的主意,除非你是在做学校的作业或者只是想随便玩玩,我真的建议你重新考虑这个想法。
因为类是元类的一个实例,所以一种方法是使用自定义的元类:
>>> Meta = type('Meta', (type,), {'__repr__': lambda cls: 'class A'})
>>> A = Meta('A', (object,), {'__repr__': lambda self: 'instance of class A'})
>>> A
class A
>>> A()
instance of class A
你想了解的东西叫做“ metaclass”(类的类)……就像 a
是类 A
的一个实例一样,A
也是一个类的实例,这个类就是 metaclass。默认情况下,Python 的类都是 type
类的实例(唯一的例外是 Python 2,它有一些旧式的“老式”类,这些类没有继承自 object
)。你可以通过执行 type(A)
来检查……它应该返回 type
本身(是的,这个对象有点复杂)。
metaclass 非常强大,理解起来也有点难,所以我觉得它值得更详细的解释……一个好的起点是这个 StackOverflow 问题:什么是 Metaclass。
针对你的具体问题,在 Python 3 中,下面的代码创建了一个 metaclass,它将 len(A)
关联到调用 A 的一个类方法:
class LengthMetaclass(type):
def __len__(self):
return self.clslength()
class A(object, metaclass=LengthMetaclass):
@classmethod
def clslength(cls):
return 7
print(len(A))
(注意:上面的例子是针对 Python 3 的。对于 Python 2,语法稍有不同:你需要使用 class A(object):\n __metaclass__=LengthMetaclass
,而不是将其作为参数传递。)
之所以 LengthMetaclass.__len__
不影响 A 的实例,是因为 Python 在查找属性时,首先会检查实例字典,然后再查找类的层次结构 [A, object]
,但它从不查看 metaclass。而访问 A.__len__
时,首先会查看实例 A
,然后再查找它的类层次结构,这个结构是 [LengthMetaclass, type]
。