Add methods to a class at runtime?

Gerhard Häring gerhard.haering at gmx.de
Sun Sep 1 14:44:39 EDT 2002


Robert Oschler wrote in comp.lang.python:
> "Gerhard Häring" <gerhard.haering at gmx.de> wrote:
>> >>> class Foo: pass
>> ...
>> >>> foo = Foo()
>> >>> foo.bar()
>> Traceback (most recent call last):
>>   File "<stdin>", line 1, in ?
>> AttributeError: Foo instance has no attribute 'bar'
>> >>> def bar(self): print "bar"
>> ...
>> >>> Foo.bar = bar
>> >>> foo.bar()
>> bar
>> >>>
> 
> Gerhard,
> 
> Thanks but I need a little bit more detail.  Suppose I want to do it from
> within code?  For example, I create a function called
> AddBarToFoo(FooObject), that given a object of type Foo (FooObject) adds the
> Bar method to it dynamically, what would be the syntax then?

To get the class of an instance, you can query its __class__
attribute.

> Would I have to put the method declaration code, which you show
> being typed in to the interpreter, in a string and then eval/exec
> it?

No, you hardly ever need to use eval or exec. Sometimes you only want
to "specialize" an existing, more generic function. For a real-life
example, here's something I experimented with yesterday:

# [snip generic_insert, generic_update]
def generic_delete(tablename, id):
    cursor = getdb().cursor()
    statement = "DELETE FROM %s WHERE id=%%s" % tablename
    cursor.execute(statement, (id,))

def make_functions(tablename):
    globals()[tablename + "_DELETE"] = lambda id: generic_delete(tablename, id)
    
# Create a specialized DELETE function for the table TEST which will
# be named TEST_DELETE (this will be a specialized generic_delete):
make_functions("TEST")

# Execute the newly created function:
TEST_DELETE(25)

I never really needed to add methods to classes on-the-fly, but the
above technique came in useful a few times. One other thing I found
useful is dynamically creating a new class (with certain class
attributes) using the new module.

As in certain other languages starting with "P", not everything you
/can/ do in Python is actually very useful, or necessarily a good
idea.

Gerhard
-- 
mail:   gerhard <at> bigfoot <dot> de       registered Linux user #64239
web:    http://www.cs.fhm.edu/~ifw00065/    OpenPGP public key id AD24C930
public key fingerprint: 3FCC 8700 3012 0A9E B0C9  3667 814B 9CAA AD24 C930
reduce(lambda x,y:x+y,map(lambda x:chr(ord(x)^42),tuple('zS^BED\nX_FOY\x0b')))



More information about the Python-list mailing list