Dynamically Adding Methods With Metaprogramming : Ruby and Python
I came across an interesting post Metaprogramming: Ruby vs. Javascript, which discusses and contrasts about how metaprogramming can be implemented in Ruby and Javascript. I thought it might be fun to document the same from a python perspective as well.
Here are the discussed samples. All the ruby code is quoted from from the blog post linked to above whereas the python code is what I wrote.
1. Initial class declaration and initialisation
We first declare a Ninja class and create two instances.
Ruby
3. Add a method to an instance
In this case we add a method only to a particular instance. The same method will not be available to other instances of the same class.
Ruby
123456
defdrew.throw_starputs"throwing a star"enddrew.throw_star# => throwing a star
Python
1234567
importtypesdefthrow_star(self):print'throwing a star'drew.throw_star=types.MethodType(throw_star,drew)drew.throw_star()# => throwing a star
4. Invoke a method dynamically
In this case we supply the method name as a string and invoke it.
Ruby
5. Defining class level methods dynamically with closures
Here a class level method is defined which closes over some of the attributes in its context (in this case the method color is able to access the variable color_name as a closure).
Ruby
12345678910
color_name='black'Ninja.send(:define_method,'color')doputs"#{name}'s color is #{color_name}"enddrew.color# => Drew's color is blackadam.color# => Adam's color is black
Python
12345678910
color_name='black'defcolor(self):print"%s's color is %s"%(self.name,color_name)Ninja.color=colordrew.color()# => Drew's color is blackadam.color()# => Adam's color is black
6. Defining a method dynamically on an instance that closes over local scope and accesses the instance’s state
Note that in this case the function is being defined on the instance using a dynamic name (‘swing’)
Ruby