我不太了解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()
这不能按预期工作,因为输出如下:
x = 25
y = 4
x = 25
y = 4
我希望它是:
x = 25
y = 4
x = 25
y = woohoo
我尝试用这个改变Bar的init方法:
def __init__(self):
self.foo = Foo()
self.foo.showy = showyImp
但是我收到以下错误消息:
showyImp()只需1个参数(0给定)
所以是的...我尝试使用setattr()
,但似乎与self.foo.showy = showyImp
相同。
有任何线索吗? :)
答案 0 :(得分:23)
您想了解的关于Python Attributes and Methods的所有信息。
是的,这是一个间接的答案,但它展示了许多技巧,并解释了一些更复杂的细节和“魔力”。
要获得“更直接”的答案,请考虑python's new module。特别是,请查看允许将方法“绑定”到实例的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
答案 1 :(得分:23)
从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__()
。
答案 2 :(得分:8)
如果您需要为特殊方法(对于新式类 - 这是您应该始终使用的,也是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.instance方法在这种情况下完全没用。 OTOH ...
>>> x.__class__=type('X',(X,),{'__str__':lambda self:'boo!'})
>>> print x, y
boo! baah
...分配一个新类对于这个案例和其他所有案例都很有用。顺便说一句,我希望很清楚,一旦你对给定的实例做了这个,你可以稍后在它的x.__class__
中添加更多方法和其他类属性,并且本质上只影响那个实例!
答案 3 :(得分:5)
如果您绑定到实例,则不应包含self参数:
>>> class Foo(object):
... pass
...
>>> def donothing():
... pass
...
>>> f = Foo()
>>> f.x = donothing
>>> f.x()
>>>
如果你绑定到一个类,你确实需要self参数:
>>> def class_donothing(self):
... pass
...
>>> foo.y = class_donothing
>>> f.y()
>>>
答案 4 :(得分:0)
你的例子有点扭曲和复杂,我不太明白它与你的问题有什么关系。如果你愿意,请随意澄清。
然而,假设我正在正确地阅读你的问题,你很容易做你想做的事。
class Foo(object):
def bar(self):
print('bar')
def baz():
print('baz')
在口译员......
>>> f = Foo()
>>> f.bar()
bar
>>> f.bar = baz
>>> f.bar()
baz
>>> g = Foo()
>>> g.bar()
bar
>>> f.bar()
baz
答案 5 :(得分:0)
不要这样做。
更改一个实例的方法是错误的。
以下是面向对象设计的规则。
避免魔术。
如果您不能使用继承,请使用委托。
这意味着每次你认为你需要魔法时,你应该在对象周围写一个“包装器”或Facade来添加你想要的功能。
只需写一个包装器。