Python 有没有一种方法可以实现像_ulen___;或_; eq__;这样的类方法?

Python 有没有一种方法可以实现像_ulen___;或_; eq__;这样的类方法?,python,class,Python,Class,在Python中实现\uuu len(self)方法非常容易,因此它可以处理len(inst)调用,如下所示: class A(object): def __len__(self): return 7 a = A() len(a) # gives us 7 你可以定义很多类似的方法(\uuuu eq\uuuu,\uu str\uuuu,\uu repr\uu等等)。 我知道Python类也是对象 我的问题是:我是否可以以某种方式定义,例如,\uuu len\uuuu,以使以下各

在Python中实现
\uuu len(self)
方法非常容易,因此它可以处理
len(inst)
调用,如下所示:

class A(object):

  def __len__(self):
    return 7

a = A()
len(a) # gives us 7
你可以定义很多类似的方法(
\uuuu eq\uuuu
\uu str\uuuu
\uu repr\uu
等等)。 我知道Python类也是对象

我的问题是:我是否可以以某种方式定义,例如,
\uuu len\uuuu
,以使以下各项起作用:

len(A) # makes sense and gives some predictable result

由于类是元类的实例,一种方法是使用自定义元类:

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

你要找的是所谓的“元类”。。。就像
a
是类
a
的实例一样,
a
也是类的实例,称为元类。默认情况下,Python类是
类型
类的实例(唯一的例外是Python2,它有一些遗留的“旧式”类,这些类不是从
对象
继承的)。您可以通过执行
键入(A)
来检查这一点。。。它应该返回
type
本身(是的,该对象有点过载)

元类是强大的,而且足以扭曲大脑,比我将要写的快速解释更值得。。。一个好的起点是这个stackoverflow问题:

对于您的特定问题,对于Python 3,下面将创建一个别名为
len(a)
的元类,以调用

class LengthMetaclass(type):

    def __len__(self):
        return self.clslength()

class A(object, metaclass=LengthMetaclass):

    @classmethod
    def clslength(cls):
        return 7

print(len(A))
(注意:上面的示例适用于Python3。Python2的语法略有不同:您可以使用
类A(对象):\n\uuuuuuu元类\uuuuuuu=LengthMetaclass
而不是将其作为参数传递。)

之所以
LengthMetaclass.\uuu len\uuuu
不影响
A
的实例,是因为Python中的属性解析首先检查实例dict,然后遍历类层次结构
[A,object]
,但它从不参考元类。而访问
A.\uu len\uuu
首先参考实例
A
,然后遍历它的类层次结构,该层次结构由
[LengthMetaclass,type]
组成,请尝试以下操作:

class Lengthy:
    x = 5
    @classmethod
    def __len__(cls):
        return cls.x
@classmethod允许您直接在类上调用它,但您的len实现将无法依赖于任何实例变量:

a = Lengthy()
len(a)

我看不出语法是如何特别重要,但是如果您真的想用一种简单的方法来实现它,那么返回len(inst)的正常len(self)只是在您的实现中让它返回一个所有实例共享的类变量:

class A:
    my_length = 5
    def __len__(self):
        return self.my_length
以后你可以这样称呼它:

len(A()) #returns 5
显然,这会创建类的临时实例,但长度只对类的实例有意义,而对类(类型对象)的概念没有意义


编辑元类听起来是一个非常糟糕的主意,除非你在为学校做些什么或只是胡闹,否则我真的建议你重新思考这个想法。

“我可以吗?”或“我应该吗?”也许你可以详细说明你的预期用例,因为我无法想象这可能有用的任何情况。它可能会帮助我们更好地解决这个问题(如果有更好的方法),或者至少帮助我们更好地完成您的目标。@ChrisLutz如果类跟踪有多少实例被实例化,或者有一个所有实例的列表,该怎么办?我认为使用一个可枚举类型的静态字段/属性/成员,像
len(class.instances)
这样使用,对于下一个开发人员来说,比
len(class)
更具可读性和直观性。我直觉上认为
len(TheClass)
要么给出一个错误,要么计算类本身的字段/属性/成员的数量,行为类似
len(TheClass.\uu dict\uuuu.keys())
谢谢,这是完美的:)非常非常酷的解释注意,在Python 3中,元类的定义类似于
类a(对象,元类=LengthMetaclass):
这通常不是您想要的,因为它不使用对象的实例变量,但为所有实例返回相同的值。通常您只希望在类中实现len。请参阅。哇,与Eli Collins的元类解释相比,这太简单了。有什么问题吗?看起来值将是相同的对于所有冗长的实例?@huggie关键是它不起作用。
len(longing)
将抛出一个异常。这个答案应该被删除。
len(a)
在Python 3.7.3中似乎返回
5
。@user1338062
len
将在实例上工作(
leng(longing())
),但在类上不工作(
leng)
)。它会引发
类型错误:“type”类型的对象没有len()