views:

108

answers:

4

I'd like to modify 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?

A: 

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.

CrazyJugglerDrummer
Ok, how can I do that programmaticly? I'd like to apply this modification to a lot of classes. I don't want to extend all of them by hand.
Juanjo Conti
You might want to use a class decorator which returns a modified version for the class. Then you only have to add "@yourdecorator" at the top of each class that should be modified.
AndiDog
+1  A: 

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.

Alex Martelli
How could you overload the \_\_add__ method for the changed class?
Juanjo Conti
Exactly the same way.
Lennart Regebro
+3  A: 

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?

mzz
A: 

subclass:


class int(int):
  def foo(self):
   print "foo"

int(2).foo()
wiso