[英]methods of metaclasses on class instances
我想知道在元类上声明的方法会发生什么。 我希望如果你在元类上声明一个方法,它最终将成为一个类方法,但是,行为是不同的。 例
>>> class A(object):
... @classmethod
... def foo(cls):
... print "foo"
...
>>> a=A()
>>> a.foo()
foo
>>> A.foo()
foo
但是,如果我尝试定义一个元类并给它一个方法foo,它似乎对类有效,而不是对于实例。
>>> class Meta(type):
... def foo(self):
... print "foo"
...
>>> class A(object):
... __metaclass__=Meta
... def __init__(self):
... print "hello"
...
>>>
>>> a=A()
hello
>>> A.foo()
foo
>>> a.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'foo'
这到底发生了什么?
编辑 :碰撞问题
你提出了一个好点。
这是一个很好的参考 ,可以更好地理解对象,类和元类之间的关系:
我也发现这个关于描述符的引用对于 python中的查找机制非常有启发性。
但我不能说我理解为什么当A.foo
成功时A.foo
a.foo
失败。 看起来,当你查找一个对象的属性,并且python在那里找不到它时,它并没有完全查找类中的属性,因为如果它发生了,它会找到A.foo
。
编辑:
哦! 我想我明白了。 这是由于继承如何工作。 如果您考虑上述链接提供的架构,它看起来像这样:
原理上,它归结为:
type -- object
| |
Meta -- A -- a
左转意味着转到给定实例的类。 上升意味着去父母 。
现在,继承机制使查找机制在上面的模式中向右转 。 它变成a → A → object
。 它必须这样做才能遵循继承规则! 为清楚起见,搜索路径是:
object
^
|
A <-- a
然后,显然,将找不到属性foo
。
当你查找的属性foo
的A
,但是,人们发现 ,由于查找路径是:
type
^
|
Meta <-- A
当人们想到继承如何运作时,这一切都是有意义的。
规则是这样的:当在对象上搜索属性时,也考虑对象的类及其父类。 但是, 不考虑对象的类的元类。 当你访问一个类的属性,类的类是元类,因此它被认为。 从对象到其类的回退不会触发对类的“正常”属性查找:例如,无论是在实例上还是在其类上访问属性,都会以不同方式调用描述符。
方法是可调用的属性(并且具有__get__
方法,使得'self'自动传递。)这使得如果在类上调用它们但在实例上不可用,则元类上的方法就像classmethods。
我理解它的方式是Meta是一个类,A是它的一个实例。 因此,当您调用A.foo()时,它会检查对象及其类。 因此,在尝试A.foo时,它首先查看A本身持有的方法,然后查看其类的方法Meta。 因为A本身没有方法foo,所以它使用Meta之一,因此真正执行Meta.foo(A)。
类似地,当尝试a.foo时,它将首先查看a。 作为一个没有方法foo,它将通过A看。但是A也没有方法foo,因为foo在Meta中保存。 由于a和A都不包含foo,因此会引发AttributeError。
我尝试使用变量和函数,在类Meta中加入属性txt ='txt',这也可以由A访问,但不是a。 所以,我倾向于认为我的理解是正确的,但我只是在猜测。
已接受答案中的链接已经消失,至少对我而言。 所以我想做一些补充:
并在我看来给出两个关键点:
object.__getattribute__
控件实例的属性访问。 type.__getattribute__
控件类的属性访问。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.