Adding methods to an object

  • Thread starter Gabriele *darkbard* Farina
  • Start date
G

Gabriele *darkbard* Farina

Hi, there is a way to add methods to an object dynamically? I need to
do something like this. I remember python allowed this ...

class A(object):
def do(s, m):
print m

@staticmethod
def init(obj):
obj.do = A.do

class Test(object):
pass

o = Test()
A.init(o)

o.do(10)

Now it gives me an error ... unbound method ...

tnx, gabriele
 
B

bearophileHUGS

This isn't code of mine, it's probably from the cookbook, maybe with
little changes:

| def addMethod(object, method, name=None):
| if name is None: name = method.func_name
| class newclass(object.__class__):
| pass
| setattr(newclass, name, method)
| object.__class__ = newclass

name is the name for the new method, if it's None then the name of
"method" is used.

Bye,
bearophile
 
R

rcramsdell

gabriele,

This works (A, Test, and o as defined by you):
10

Your problem is that do() really has two parameters, an A instance and
whatever you want to print.

Why not do this:
.... print m
....10

Robert
 
S

Steven D'Aprano

Hi, there is a way to add methods to an object dynamically?

Yes. There are three different sorts of methods, and three ways of adding
them.

py> class Parrot:
.... def __init__(self):
.... pass
py> # Parrot is the class.
py> # Parrot() is an instance of the class.

Firstly, you want an ordinary method with a "self" parameter, as if you
had defined it when you created the class.


py> def spam(self):
.... return "Spam comes from %s" % self
....
py> Parrot.spam = spam

Now we try calling it from an instance:

py> Parrot().spam()
'Spam comes from <__main__.Parrot instance at 0xed498fec>'

If you try to call spam direct from the class, it fails:

py> Parrot.spam()
TypeError: unbound method spam() must be called with Parrot instance as
first argument (got nothing instead)



The second way of adding a method is a class method. Class methods don't
know about the instance you call them from, only the class.

py> def fjords(cls):
.... return "I'm pining for the fjords at %s." % cls
....
py> Parrot.fjords = classmethod(fjords)

Now we can call it from either the class or any instance, and get the
exact same result. fjords just can't see the instance, only the class:

py> Parrot.fjords()
"I'm pining for the fjords at __main__.Parrot"
py> Parrot().fjords()
"I'm pining for the fjords at __main__.Parrot"



Lastly, we can add a static method, that doesn't know about either the
class or the instance:

py> def ham():
.... return "Genuine pig product."
....
py> Parrot.ham = staticmethod(ham)
py> Parrot.ham()
'Genuine pig product'
py> Parrot().ham()
'Genuine pig product'



Summary:

If you write the function with a "self" argument, and just add it to the
class, you must call that method using an instance. This is an ordinary
instance method, as if you had created the class with it.

If you write the function with a "cls" argument, you must add it to the
class with a classmethod() call, and then call it from either the class or
an instance. This method cannot access the instance that calls it, only
the class.

If you write the function without a "self" or "cls" argument, you must add
it to the class with a staticmethod() call. This method cannot access
either the class or the instance object.
 

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
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top