从类中的一个方法继承的两个方法在实例中是不同的,不是吗?

sav*_*oto 3 python inheritance python-3.x

有人可以解释为什么会这样吗?

class Foo:
    def bar(self):
        pass

a = Foo()
b = Foo()

a.bar == b.bar # False
a.bar is b.bar # False
Run Code Online (Sandbox Code Playgroud)

我认为他们都继承了类方法,这是一种方法.

jua*_*aga 5

通过在类上定义的实例访问函数时,每次都会创建一个bound-method对象.来自文档:

调用方法时到底发生了什么?您可能已经注意到,x.f()上面没有参数调用,即使f()指定参数的函数定义.这个论点怎么了?当一个需要参数的函数被调用而没有任何东西时,Python肯定会引发异常 - 即使实际上没有使用该参数......

实际上,您可能已经猜到了答案:方法的特殊之处在于实例对象作为函数的第一个参数传递.在我们的示例中,调用x.f()完全等同于 MyClass.f(x).通常,使用n个参数列表调用方法等效于使用通过在第一个参数之前插入方法的实例对象而创建的参数列表来调用相应的函数.

如果您仍然不了解方法的工作原理,那么查看实现可能会澄清问题.当引用不是数据属性的实例属性时,将搜索其类.如果名称表示作为函数对象的有效类属性,则通过打包(指向)实例对象和刚在抽象对象中找到的函数对象来创建方法对象:这是方法对象.

请注意,每次访问方法都会发生这种情况:

>>> class Foo:
...    def bar(self): pass
...
>>> f = Foo()
>>> f.bar is f.bar
False
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?好吧,实际上,函数是描述符对象,注意存在一个__get__:

>>> def func(): pass
...
>>> func.__get__
<method-wrapper '__get__' of function object at 0x101e38ae8>
Run Code Online (Sandbox Code Playgroud)

换句话说,您可以将Python函数视为如此实现:

class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        if obj is None:
            return self
        return types.MethodType(self, obj)
Run Code Online (Sandbox Code Playgroud)

当然,它们不是用Python实现的(至少在CPython中!).

另请注意,直接在类上访问函数当然不会这样做(至少在你已经在你的问题上标记的Python 3上):

>>> Foo.bar is Foo.bar
True
Run Code Online (Sandbox Code Playgroud)