根据Python 2.7.12文档,
当属性是用户定义的方法对象时,新方法 object仅在从中检索它的类时创建 与存储在中的类相同或派生类 原始方法对象; 否则,原始方法对象是 按原样使用。
我试图通过编写代码来理解这一段:
# Parent: The class stored in the original method object
class Parent(object):
# func: The underlying function of original method object
def func(self):
pass
func2 = func
# Child: A derived class of Parent
class Child(Parent):
# Parent.func: The original method object
func = Parent.func
# AnotherClass: Another different class, neither subclasses nor subclassed
class AnotherClass(object):
# Parent.func: The original method object
func = Parent.func
a = Parent.func
b = Parent.func2
c = Child.func
d = AnotherClass.func
print b is a
print c is a
print d is a
输出结果为:
False
False
False
我希望它是:
False
False
True
答案 0 :(得分:3)
每次编写Parent.func
时,都会获得一个新的未绑定方法对象。所以AnotherClass.func
永远不会改变,但Parent.func
会改变。如果你这样做,你可以看到这个:
a = Parent.func
a2 = Parent.func
b = Parent.func2
c = Child.func
d = AnotherClass.func
d2 = AnotherClass.func
然后:
>>> a is a2
False
>>> d is d2
True
因此,您对“原始方法对象”的评论有些误导。评估Parent.func
的代码的每个部分都获得了不同的方法对象。 (请注意,您提供的引用不适用于Parent.func
,因为func
中写的Parent
不是方法对象;它是一个函数对象。只有当您访问时才通过编写Parent.func
来获取方法对象的属性。)
我在这里添加一点来澄清你给出的报价。
我认为你误解了引用的内容。这可能是因为引用对于“属性”与获取该属性所检索的值之间的区别有些模糊。
让我通过分离两个概念来澄清。在像something.attr
这样的表达式中,我将使用“原始值”来表示存储在类/对象字典中的实际值,即something.__dict__['attr']
的值。我将使用“评估值”来指代评估something.attr
的实际结果。两者之间的区别在于,在原始值上激活descriptor protocol以获得评估值。
您引用的文档描述了 raw 值是方法对象的情况。在Child和AnotherClass的定义中就是这种情况。引用不适用于Parent内的func
,因为在这种情况下,原始值不是方法;这是一个功能。在这种情况下,文件的以下段落适用:
通过检索用户定义的函数对象创建用户定义的方法对象时...
换句话说,您引用的文档(“当属性是用户定义的方法对象时”)适用于以下情况:
obj = [a method object]
class Foo(object):
attr = obj
您引用的文档不适用于以下情况。在这种情况下,属性是“用户定义的函数对象”:
func = [a function object]
class Foo(object):
attr = func
在您的示例中,没有“原始方法对象”。在定义类之后,您只能获取方法对象。 “原始”对象是一个功能对象。当您在类体中编写func
时,您正在定义一个函数;只有当您访问 Parent.func
时才能获得方法对象。