是否可以修改单个实例的方法实现而不影响同类的其他实例?
我对Python不是很了解(之前从没用过 :D),但是我在网上找不到相关的信息。也许我没有问对问题,不过我还是来试试:
我想要改变一个实例中特定方法的实现。当我在网上搜索时,发现可以这样做,但这样会影响到同一类的所有其他实例。例如:
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()
这并没有按预期工作,因为输出是这样的:
x = 25
y = 4
x = 25
y = 4
而我希望它是这样的:
x = 25
y = 4
x = 25
y = woohoo
我尝试用这个来改变Bar的初始化方法:
def __init__(self):
self.foo = Foo()
self.foo.showy = showyImp
但我得到了以下错误信息:
showyImp() 需要一个参数(给了0个)
所以……我尝试使用 setattr()
,但看起来这和 self.foo.showy = showyImp
是一样的。
有什么线索吗? :)
6 个回答
如果你需要为一个特殊的方法做一些处理(在新的类中——也就是你应该一直使用的类型,Python 3 里只有这种类型——这个方法是根据类来查找的,而不是根据实例),你可以创建一个每个实例都有自己类的方式,比如说……:
self.foo = Foo()
meths = {'__str__': lambda self: 'peekaboo!'}
self.foo.__class__ = type('yFoo', (Foo,), meths)
编辑:有人让我解释一下这种方法相对于 new.instancemethod 的优点……:
>>> 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
如你所见,在这种情况下,new.instancemethod 完全没用。另一方面……:
>>> x.__class__=type('X',(X,),{'__str__':lambda self:'boo!'})
>>> print x, y
boo! baah
……为这个情况和其他所有情况分配一个新类效果很好。顺便说一下,正如我希望你能明白的,一旦你对某个实例做了这个处理,你就可以在它的 x.__class__
上添加更多的方法和其他类属性,只会影响到这个特定的实例!
这个回答已经过时了;下面的回答适用于现代的Python
关于Python的属性和方法,你想知道的一切。
是的,这个回答有点间接,但它展示了许多技巧,并解释了一些更复杂的细节和“魔法”。
如果你想要一个“更直接”的回答,可以看看Python的new模块。特别是,看看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
从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)
不过,正如另一个回答提到的,这个方法对新式类的“魔法”方法是无效的,比如__str__()
。