有没有办法将__len__或__eq__等方法实现为classmethods?

时间:2011-10-04 01:32:46

标签: python class

在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 个答案:

答案 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 对象)并不真正有意义。

编辑元类听起来是个很糟糕的主意,除非你是在为学校做点什么或者只是在捣乱,否则我真的建议你重新考虑这个想法..