在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
答案 0 :(得分:42)
您正在寻找的内容称为“元类”...就像a
是类A
的实例一样,A
也是类的实例,引用作为元类。默认情况下,Python类是type
类的实例(唯一的例外是在Python 2下,它有一些遗留的“旧样式”类,它们不是从object
继承的)。您可以通过执行type(A)
来检查它...它应该返回type
本身(是的,该对象已经过载了一点)。
元类是强大的,大脑扭曲足以得到比我即将写的快速解释更多...一个好的起点将是这个stackoverflow问题:What is a Metaclass。
对于您的特定问题,对于Python 2,以下内容创建了一个元类,它使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的工作方式类似,但您可以使用class A(object, metaclass=LengthMetaclass):
代替__metaclass__ = LengthMetaclass
。
LengthMetaclass.__len__
不影响A
的实例的原因是Python中的属性解析首先检查实例dict,然后遍历类层次结构[A, object]
,但它从不咨询元类。访问A.__len__
首先访问实例A
,然后执行它的类层次结构,该层次结构由[LengthMetaclass, type]
组成。
答案 1 :(得分: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
答案 2 :(得分:0)
试试这个:
class Lengthy:
x = 5
@classmethod
def __len__(cls):
return cls.x
@classmethod允许你直接在类上调用它,但你的len实现不能依赖任何实例变量:
a = Lengthy()
len(a)
答案 3 :(得分:0)
我看不出语法特别重要,但如果你真的想要一个简单的方法来实现它,就是正常的 len(self) 返回 len(inst) 但在你的实现使它返回一个所有实例共享的类变量:
class A:
my_length = 5
def __len__(self):
return self.my_length
你以后可以这样称呼它:
len(A()) #returns 5
显然这会创建您的类的临时实例,但长度仅对类的实例有意义,而对类的概念(Type 对象)并不真正有意义。
编辑元类听起来是个很糟糕的主意,除非你是在为学校做点什么或者只是在捣乱,否则我真的建议你重新考虑这个想法..