为什么对实例方法的引用存储在每个实例对象中而不是存储在类对象中?

max*_*max 4 python methods internals python-3.x

据我所知,类的每个实例都存储对实例方法的引用.

我认为,从概念上讲,类的所有实例都具有相同的实例方法.如果是这样,内存节省和逻辑清晰度似乎都表明实例方法应该存储在类对象而不是实例对象中(实例对象通过类对象查找它们;当然,每个实例都有一个对它的引用类).为什么不这样做?

第二个问题.为什么实例方法不能以类似于实例属性的方式访问,即通过__dict__或通过其他系统属性?有没有办法查看(也许更改)名称和实例方法的引用?

编辑:

哎呀,对不起.我完全错了.我看到了以下Python 2代码,并错误地从中得出结论,实例方法存储在实例中.我不确定它是做什么的,因为我不使用Python 2,并且new已经从Python 3中消失了.

import new
class X(object):
  def f(self):
    print 'f'
a = X()
b = X()
def g(self):
  print 'g'
# I thought this modified instance method just in a, not in b
X.f = new.instancemethod(g, a, X)
Run Code Online (Sandbox Code Playgroud)

Kat*_*iel 6

Python中对象的属性查找非常重要.但实例方法肯定不存储在实例对象上!

属性访问的默认行为是从对象的字典中获取,设置或删除属性.例如,a.x有一个查找链,从a.__dict__['x'],然后type(a).__dict__['x'],继续通过type(a)排除元类的基类开始.

(docs)

请注意,这可以存储上的一个实例的功能.但那不是实例方法!当解释器查找属性并发现它是(a)函数和(b)类对象时,它会自动将其包装在已传递的绑定方法对象中self.


有没有办法查看(也许更改)名称和实例方法的引用?

那么,您可以在定义后修改类对象.但我认为你的意思是"你能让x某个特定实例的方法做些不同的事情吗?"

这是Python,答案是肯定的:只是定义a.x为一些新功能.然后,在查看课程之前,您将获得该功能.

但是,当您尝试理解代码时,这可能会给您带来很多困惑!

  • 覆盖方法,即使是基于每个实例,也不一定会破坏LSP或任何其他此类合同.您提供的方法也可能与调用者的POV做同样的事情.否则,即使是子类中的多态和重写方法也是不可能的.我给了一个tenative -1但我无法在接下来的一小时内检查编辑或理由(即我无法恢复downvote). (2认同)

Sve*_*ach 5

据我所知,类的每个实例都存储对实例方法的引用.

我不知道你从哪里得到这个,但这是错的.他们没有.

为什么实例方法不能以类似于实例属性的方式访问,即通过__dict__或通过其他系统属性?

好吧,因为它们没有存储在实例上.

有没有办法查看(也许更改)名称和实例方法的引用?

由于这些引用不存在,因此您无法更改它们.您当然可以通过正常分配创建所需的任何属性,但请注意,实例上存储的函数不会像普通方法那样处理 - 隐式传递self参数的机制不适用于它们.

  • 你的答案表明提问者是错的,但不是原因. (2认同)