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]
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
:)