Discuss / Python / 有个问题谁能给我解答一下?

有个问题谁能给我解答一下?

Topic source
>>> class S:
...     pass
...
>>> def run(self,age):
...     self.age=age
...
>>> from types import MethodType
>>> S.run=MethodType(run,S)
>>> we=S()
>>> she=S()
>>> we.run(10)
>>> she.run(20)
>>> print(we.age,she.age)
20 20
>>>

这里,为什么we.run(10)会被she.run(20)覆盖呢?我只知道MethodType这个方法是在外部创建的一个链接

AlaricMurray

#2 Created at ... [Delete] [Delete and Lock User]

顺序问题,因为程序在执行we.run(20)的时候已经将age赋为20,在执行print(we.age,she.age)时,会读取属性age,而age已经是20了,所以才会两个输出都是20

改为: class S: pass

def run(self,age): self.age=age

from types import MethodType S.run=MethodType(run,S) we=S() she=S() we.run(10)//将10赋值给age print(we.age)//这里输出是10 she.run(20)//将20赋值给age print(she.age)//这里输出是20

因为你前面定义的是S.run=MethodType(run,S),在左侧S.run只是方法在类中命名,而MethodType(run,S)中右侧S为方法存放的类,查看MethodType定义可知method(function, instance) 最后一个参数本来应该是实例instance而不是class

在每次执行S.run时都会讲MethodType再执行一遍所以不对

WOWsapling

#4 Created at ... [Delete] [Delete and Lock User]

你打印一下S.age 就知道了、

MethodType里绑定的S,是一个类,并不是we,she

小肠杆菌

#6 Created at ... [Delete] [Delete and Lock User]
S.run=MethodType(run,S)
S.run
bound method run of <class '__main__.S'>

这是用MethodType绑定的结果

S.run=run
S.run
<function run at 0x00000000003F3E18>

这是直接关联的结果

然后下面的是用第二种方法的执行结果

>>> we.run(10)
>>> she.run(12)
>>> print(we.age,she.age)
10 12

MethodType绑定上的应该是一个类,然后自带一个 __call__属性,大概是把S这个类看作是一个实例处理了吧

看完了上面各位的解释,我依旧没有明白。 看讨论之前我认为下面这两句是为实例绑定方法的,而不是 from types import MethodType S.run=MethodType(run,S) 但是,看了这个写法后,我很迷茫,难道还可以用它来给类绑定一个方法吗?

这两句话,到底是怎样的存在啊? 如果也可以为类绑定一个方法,和直接关联有什么区别?用法上需要注意什么?

另外,这个

bound method run of <class '__main__.S'>

怎么理解?

在另外一个问题的高楼中发现了高人的回答,在这里mark一下。

Stu类本身并没有属性和方法,所以用这个类创建的实例也没有属性和方法。用MethodType将set_age方法绑定到Stu类,并不是将这个方法直接写到Stu类内部,而是在Stu内存中创建一个link指向外部的方法,在创建Stu实例的时候这个link也会被复制。所以不管创建多少实例,这些实例和Stu类都指向同一个set_age方法。A.set_age(10)并没有在A这个实例内部创建age属性,而是将age属性创建在外部set_age方法的内存区中。因为A和B内部link都指向外部set_age方法的内存区,所以不管A还是B在调用set_age方法的时候改变的是set_age方法内存区里的age属性,所以A改了B也就改了,如果新建一个实例C在没有调用set_age方法的前提下也会有age属性,因为C的link指向的set_age方法的内存区,而set_age之前被A或者B调用过了。

这才是正解啊~~~


  • 1

Reply