Is there a Python equivalent for Ruby's define_method
, which would allow dynamic generation of class methods?
(as can be seen in Wikipedia's Ruby example code)
Asked
Active
Viewed 1,057 times
6

Rabarberski
- 23,854
- 21
- 74
- 96
3 Answers
14
Functions are first-class objects in Python and can be assigned to attributes of a class or an instance. One way to do the same thing as in the Wikipedia example is:
colours = {"black": "000",
"red": "f00",
"green": "0f0",
"yellow": "ff0",
"blue": "00f",
"magenta": "f0f",
"cyan": "0ff",
"white": "fff"}
class MyString(str):
pass
for name, code in colours.iteritems():
def _in_colour(self, code=code):
return '<span style="color: %s">%s</span>' % (code, self)
setattr(MyString, "in_" + name, _in_colour)

Jochen Ritzel
- 104,512
- 31
- 200
- 194

Sven Marnach
- 574,206
- 118
- 941
- 841
-
This will *not* work as expected. `code` will be the same for every method. Adding a bogus default parameter `code=code` like `name` will fix it. – Mar 27 '11 at 12:52
-
Note the `code=code` in the inner function, you have to pass the variable you loop over to the function like this. – Jochen Ritzel Mar 27 '11 at 12:52
-
@delnan: This was a mistake. I meant to pass in `code=code` instead of `name=name`. – Sven Marnach Mar 27 '11 at 12:57
-
Note that you can do this without adding a dummy parameter to the function, but it's beyond the scope of the question (closures). It's just a difference of scoping rules. – Glenn Maynard Mar 27 '11 at 16:36
2
In Python, you can just set a method on a class:
>>> class Spam:
... def __init__(self, x):
... self.value = x
...
>>> Spam.getvalue = lambda self: self.value
>>> ham = Spam('ham')
>>> ham.getvalue()
'ham'
Fancier stuff is possible with decorators.

Fred Foo
- 355,277
- 75
- 744
- 836
0
You just assign a function as a new attribute to a class:
def replacement_method(self):
print self.name
class Foo(object):
def __init__(self, name):
self.name = name
# .... whatever
setattr(Foo, "printMyName", replacement_method) # assign it
Foo("Joe").printMyName() # call it
If you don't need a computable name (as are strings in the sample from Wikipedia), you can have it even cleaner:
Foo.printMyName = replacement_method

9000
- 39,899
- 9
- 66
- 104