Dynamic Method Creation in Python

I like to use this example to totally freak out Java people. Cool dynamic languages such as Python or Ruby allow you to modify the definition of any class on the fly. Javascript let’s you do that too, but then again Javascript does not really have classes right now. It’s a prototype based language – at least until ECMAScript 4 descends from heavens in a beam of heavenly light and will bring forth much awesomeness. Here is how you do it in Python:

Observe:

>>> class Person:
...     def __init__(self, fname, lname):
...             self.fname=fname
...             self.lname=lname
...
>>> john = Person("John", "Smith")
>>>
>>> Person.whatisyourname = lambda p: "My name is " \
...     + p.fname + " " + p.lname
>>>
>>> john.whatisyourname()
'My name is John Smith'

Every new instance of Person will now have a whatisyourname() method. C and Java people are probably sneering right now, at how insecure this is, how it breaks encapsulation and etc. I used to be like that too, but I reformed. What I see here is raw power.

I’m putting this here because I was trying to do closures in Python but found out you can’t really do them. Python has lambda functions instead which are really a lisp concept. The only difference between a Python lambda function and a closure is that lambda must evaluate to something. In other words, it’s body must be an expression rather than a statement. Which makes perfect sense in Lisp because it has no statements. In Lisp everything is an expression – and frankly, that is not a bad idea. Lets you chain stuff pretty nicely.

If you need to use Python statements however, you can’t use lambda. You just have to use regular assignment:

>>> def foo(self):
...     if(self.fname < self.lname):
...             print "foo"
...     else:
...             print "bar"
...
>>> Person.foo = foo
>>> john.foo()
foo
>>> zack = Person("Zack", "Abrams")
>>> zack.foo()
bar

Of course the downside here is that this is not a closure, and that the method definition exists outside the class on its own which can contribute to clutter in your code. Then on the other hand, perhaps this isn’t so bad as it allows you to do stuff like:

>>> foo(john)
foo
>>> foo(zack)
bar
>>> foo = Person.whatisyourname
>>> foo(john)
'My name is John Smith'

I guess that’s part of Python’s charm that standalone functions can easily become instance methods and instance methods can be easily used as standalone functions.

[tags]python, closures, lambda, lisp[/tags]

This entry was posted in programming and tagged . Bookmark the permalink.



One Response to Dynamic Method Creation in Python

  1. ido ISRAEL Mozilla Firefox Windows says:

    you could use the hybrid version:

    >>> def printf(s, *args):
    ... print s % args
    ...
    >>> Person.bar = lambda p: printf("foo") if p.fname > p.lname else printf("bar")
    >>> john.bar()
    bar

    just stick printf into a common import file, and use it whenever you need to avoid statements

    oh, and I thought you would like this:
    Sales Guy vs. Web Dude
    http://blip.tv/file/1015028
    :)

    Reply  |  Quote

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>