是否可以在不更改同一类的所有其他实例的情况下更改实例的方法实现?

Thi*_*tte 20 python

我不太了解python(之前从未使用过它:D),但我似乎无法在网上找到任何东西.也许我只是没有谷歌正确的问题,但在这里我去:

我想更改实例的特定方法的实现.当我用Google搜索它时,我发现你可以这样做,但它改变了同一个类的所有其他实例的实现,例如:

def showyImp(self):
    print self.y

class Foo:
    def __init__(self):
        self.x = "x = 25"
        self.y = "y = 4"

    def showx(self):
        print self.x

    def showy(self):
         print "y = woohoo"

class Bar:
    def __init__(self):
        Foo.showy = showyImp
        self.foo = Foo()

    def show(self):
        self.foo.showx()
        self.foo.showy()

if __name__ == '__main__':
    b = Bar()
    b.show()
    f = Foo()
    f.showx()
    f.showy()
Run Code Online (Sandbox Code Playgroud)

这不能按预期工作,因为输出如下:

x = 25

y = 4

x = 25

y = 4

我希望它是:

x = 25

y = 4

x = 25

y =呜呼

我尝试用这个改变Bar的init方法:

def __init__(self):
    self.foo = Foo()
    self.foo.showy = showyImp
Run Code Online (Sandbox Code Playgroud)

但是我收到以下错误消息:

showyImp()只需要1个参数(给定0)

所以是的...我尝试过使用setattr(),但看起来和它一样self.foo.showy = showyImp.

任何线索?:)

小智 25

从Python 2.6开始,您应该使用types模块的MethodType类:

from types import MethodType

class A(object):
    def m(self):
        print 'aaa'

a = A()

def new_m(self):
    print 'bbb'

a.m = MethodType(new_m, a)
Run Code Online (Sandbox Code Playgroud)

然而,正如另一个答案指出的那样,这对于新式课程的"魔术"方法不起作用,例如__str__().


小智 24

关于Python属性和方法你想知道的一切.

是的,这是一个间接的答案,但它展示了许多技术并解释了一些更复杂的细节和"魔力".

对于"更直接"的答案,请考虑python的新模块.特别是,请查看instancemethod函数,该函数允许将方法"绑定"到实例 - 在这种情况下,允许您在方法中使用"self".

import new
class Z(object):
  pass
z = Z() 
def method(self):
  return self
z.q = new.instancemethod(method, z, None)
z is z.q()  # true
Run Code Online (Sandbox Code Playgroud)

  • `zq = new.instancemethod(method,z,None)`的python 3等价物是`zq = types.MethodType(method,z)`.记得导入`types`而不是`new`. (8认同)
  • 链接断开。 (2认同)

Ale*_*lli 8

如果你需要为一个特殊的方法(对于一个新式的类 - 这是你应该一直使用的,也是Python 3中唯一的类 - 在类中查找,而不是实例) ,你可以只创建一个实例类,例如...:

self.foo = Foo()
meths = {'__str__': lambda self: 'peekaboo!'}
self.foo.__class__ = type('yFoo', (Foo,), meths)
Run Code Online (Sandbox Code Playgroud)

编辑:我被要求澄清这种方法的优点,新的.实例方法......:

>>> class X(object): 
...   def __str__(self): return 'baah'
... 
>>> x=X()
>>> y=X()
>>> print x, y
baah baah
>>> x.__str__ = new.instancemethod(lambda self: 'boo!', x)
>>> print x, y
baah baah
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,new.instance方法在这种情况下完全没用.OTOH ...:

>>> x.__class__=type('X',(X,),{'__str__':lambda self:'boo!'})
>>> print x, y
boo! baah
Run Code Online (Sandbox Code Playgroud)

......分配一个新课程对于这个案例和其他所有人都很有用.顺便说一下,我希望很清楚,一旦你对给定的实例做了这个,你可以在以后添加更多的方法和其他类属性,x.__class__并且本质上只影响那个实例!


Jas*_*ker 5

如果要绑定到实例,则不应包含self参数:

>>> class Foo(object):
...     pass
... 
>>> def donothing():
...     pass
... 
>>> f = Foo()
>>> f.x = donothing
>>> f.x()
>>> 
Run Code Online (Sandbox Code Playgroud)

但是,如果要绑定到类,则需要使用self参数:

>>> def class_donothing(self):
...     pass
... 
>>> foo.y = class_donothing
>>> f.y()
>>> 
Run Code Online (Sandbox Code Playgroud)

  • 我需要绑定到实例,并且需要访问“ self”,并且我不能修改该方法的现有调用过程,这就是为什么我不能执行“ self.foo.showy(self.foo)”的原因。 (2认同)