duncan smith wrote: > Hello, > I have a lot of functions that take an instance of a particular > class as the first argument. I want to create corresponding methods in > the class. I have tried the following, which (when called from __init__) > creates the relevant methods in an instance (Python 3.6). > > > def init_methods(self): > for func_name, method_name in [('add', '__add__'), > ('subtract', '__sub__')]: > setattr(self, method_name, > types.MethodType(globals()[func_name], self)) > > > The problem is that e.g. > > x.__sub__(y) > > works as expected, but > > x - y > > does not (because special methods are looked up in the class rather than > the instance). > > I have tried to find examples of injecting methods into classes without > success. I have tried a few things that intuition suggested might work, > but didn't - like removing the first line above, dedenting and replacing > self with the class. This is only to save typing and make the code > cleaner, but I would like to get it right. Any pointers appreciated. TIA.
You can do this in the __ init__() method: $ cat tmp.py def add(self, other): return 42 + other def init_methods(self): cls = type(self) for methodname, funcname in [("__add__", "add")]: func = globals()[funcname] setattr(cls, methodname, func) class Demo: def __init__(self): init_methods(self) x = Demo() print(x + 100) $ python3 tmp.py 142 but the __add__() method (to take the example above) is shared by all instances. You are either doing too much work by setting it again and again in every Demo.__init__() call or you are changing the behaviour of previously initialised Demo instances (if the last init_methods() sets the method to a different function) and confuse yourself. Have you considered a mix-in class instead? Like $ cat tmp.py def add(self, other): return 42 + other class CommonMethods: __add__ = add class Demo(CommonMethods): pass x = Demo() print(x + 100) $ python3 tmp.py 142 This is much cleaner, and if you insist you can set up CommonMethods programmatically with CommonMethods = type( "CommonMethods", (), {m: globals()[f] for m, f in [("__add__", "add")]} # without globals() and probably better: # {m: f for m, f in [("__add__", add)]} ) though personally I don't see the point. -- https://mail.python.org/mailman/listinfo/python-list