ma*********@wp.pl a écrit :
First of all, please don't flame me immediately.
Granted - we'll do it later then !-)
I did browse archives
and didn't see any solution to my problem.
Assume I want to add a method to an object at runtime. Yes, to an
object, not a class - because changing a class would have global
effects and I want to alter a particular object only. The following
approach fails:
class kla:
x = 1
def foo(self):
print self.x
k = kla()
k.foo = foo
k.foo()
I know where the problem is. The method shouldn't have 'self'
parameter.
Yes it should - else :
But how do I access object's attributes without it?
Hey, how's Python itself doing ?-)
The problem with your code is that foo is a function object, not a
method object. So you need to turn it into a method object - which is
(overly simplification ahead) an object that bind a function object to
an instance and takes care of passing the instance as first param to
that function (hint: google for 'descriptor').
Hopefully, function objects provide a method that allow to bind them to
instances :
class Toto(object):
.... def __init__(self, name): self.name = name
.... t1, t2 = Toto('t1'), Toto('t2')
def fun(self):
.... print self.name t1.fun = fun.__get__(t1)
t1.fun()
t1
FWIW, you would have the same result (which much less pain) by simply
passing the instance to the function !-) (there's nothing special about
the word 'self')
If what you want to do is to provide a specific implementation for a
given method on a per-instance base, you can do it much more explicitely:
class MyObject(object):
def __init__(self, name, custom_do_this=None):
self.name = name
self._custom_do_this = custom_do_this
def _do_this_default(self):
return "default do_this implementation for %s" % self.name
def do_this(self):
if callable(self._custom_do_this):
return self._custom_do_this(self)
else:
return self._do_this_default()
def custom_do_this(obj):
return "custom do_this implementation for %s" % obj.name
myobj = MyObject('myobj')
print myobj.do_this()
myobj._custom_do_this = custom_do_this
print myobj.do_this()
Agreed, this is not exactly the same thing as *adding* a method, but
it's (IMHO) somewhat cleaner wrt/ encapsulation and LSP. (Note that you
can make the default implementation a no-op - the point here is that the
client code shouldn't have to worry about MyObject's instances having or
not having a custom implementation for do_this).
My 2 cents...