Modifying a Python class
I'd like to mo开发者_StackOverflow中文版dify all classes in Python. For example str and int and others like Person(object).
I'd like to add an attribute to them and to change the way its methods works.
Which is the best approach for this? Metaclasses?
While you can do this for classes defined in python code (it will not work for builtin ones) by reassigning their attributes please do not actually do so. Just subclass and use the subclass, or write functions that take an instance of the class as argument instead of adding your own methods. Doing what you have to mind leads to awkward, fragile code, especially if you end up using multiple libraries simultaneously that try to do this to the same classes.
Is there an actual problem you're trying to solve this way?
Built-in classes can't be modified, but you can "hide" a built-in class (or any other of course) by one of the same name.
For example, suppose that the change is to add to a bunch of classes a new attribute "foobar" whose initial value is 23, and to every instance of those classes a new attribute "murf" whose initial value is 45. Here's one way:
def changedclass(cls):
def __init__(self, *a, **k):
cls.__init__(self, *a, **k)
self.murf = 45
return type(cls.__name__, (cls,), {'foobar': 23, '__init__': __init__})
def changemany(changed, classes_by_module):
for module, classnames in classes_by_module.iteritems():
for name in classnames:
cls = getattr(module, name)
subcls = changed(cls)
setattr(module, name, subcls)
import __builtin__
import mymod
changemany(changedclass, {__builtin__: ('int', 'str'), mymod: ('Person',)})
Note that bare literals like 'ciao' and 23 will still belong to the real classes -- there's no way to change that; you'll need to use str('ciao')
and int(23)
to use the "fake" classes.
You can't edit the class directly like you might with javascript's prototype attribute, it's better if you subclass them. This let's you add the functionality you want and not force it to be used everywhere.
subclass:
class int(int):
def foo(self):
print "foo"
int(2).foo()
精彩评论