我不太了解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)
如果你需要为一个特殊的方法(对于一个新式的类 - 这是你应该一直使用的,也是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__并且本质上只影响那个实例!
如果要绑定到实例,则不应包含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)