Adding method at runtime - problem with self

M

marek.rocki

First of all, please don't flame me immediately. 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. But how do I access object's attributes without it?

Best regards,

Marek
 
D

Dennis Lee Bieber

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. But how do I access object's attributes without it?
No... the "method" should have something for "self"... The problem
is that

k.foo = foo

doesn't set up the "magic" to make foo behave like a "method"... That
is:
k.foo()
is not being translated into
foo(k)

If you explicitly pass the object "k.foo(k)", it works.


This seems to have worked:


import new

class kla(object):
def __init__(self, dummy):
self.x = dummy


def foo(self):
print self.x


k = kla(98)
j = kla(33)

k.foo = new.instancemethod(foo, k, kla)

k.foo()
j.foo()

E:\UserData\Dennis Lee Bieber\My Documents\Python Progs>python
script1.py
98
Traceback (most recent call last):
File "script1.py", line 18, in ?
j.foo()
AttributeError: 'kla' object has no attribute 'foo'

E:\UserData\Dennis Lee Bieber\My Documents\Python Progs>



--
 
?

=?ISO-8859-1?Q?Sch=FCle_Daniel?=

First of all, please don't flame me immediately. 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. But how do I access object's attributes without it?

Best regards,

Marek

k.foo(k)
would work
 
B

Bruno Desthuilliers

(e-mail address removed) 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 :
.... def __init__(self, name): self.name = name
....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...
 
M

marek.rocki

Thank you all for your responses. That's exactly what I needed to know
- how to bind a function to an object so that it would comply with
standard calling syntax.

This is largely a theoretical issue; I just wanted to improve my
understanding of Python's OOP model. Using such features in real life
code would probably be classified either as excessive magic or bad
design. Oh well, at least now I can be an informed participant of
language holy wars :)

Marek
 
B

bruno at modulix

Thank you all for your responses. That's exactly what I needed to know
- how to bind a function to an object so that it would comply with
standard calling syntax.

This is largely a theoretical issue; I just wanted to improve my
understanding of Python's OOP model. Using such features in real life
code would probably be classified either as excessive magic or bad
design.

or as a dirty-but-pragmatic workaround - just like accessing
implementation attributes. These are things that one should IMHO better
avoid if possible, but sometimes a simple hack is better than no
practical solution at all.
Oh well, at least now I can be an informed participant of
language holy wars :)

Welcome on board !-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,470
Messages
2,571,809
Members
48,797
Latest member
PeterSimpson
Top