On Fri, 03 Aug 2012 13:48:08 -0700, Tobiah wrote: > I have a bunch of classes from another library (the html helpers from > web2py). There are certain methods that I'd like to add to every one of > them. So I'd like to put those methods in a class, and pass the parent > at the time of instantiation. Web2py has a FORM class for instance. > I'd like to go: > > my_element = html_factory(FORM) > > Then my_element would be an instance of my class, and also a child of > FORM.
I cannot understand what you are actually trying to do here because you aren't giving enough information and the description you give is misleading. But from what little I can grasp, I think it sounds like an unclean, confusing design and you would be better off with either mixins, composition, or code injection. What is html_factory? By the name, it should return some HTML. But you're assigning the output to something called "my_element", which suggests it is returning only a single element of HTML. To me, I would expect that to be a string. Consequently, it isn't clear to me what you actually want, and I'm forced to make some wild guesses, and I can see a number of different alternative approaches. === Mixins === You state: There are certain methods that I'd like to add to every one of [my classes]. So I'd like to put those methods in a class, and pass the parent at the time of instantiation Don't pass the utility class at instantiation time. Use it as a mixin class. class UtilityMixin: # add "those methods" to this class pass class MyClassA(MyParentClass, UtilityMixin): pass class MyClassB(AnotherClass, UtilityMixin): pass class MyClassC(MyClassB): # already inherits from UtilityMixin pass === Composition === This frankly sounds like an abuse of inheritance. Inheritance is for modelling "is-a" relationships, not just for sticking arbitrary lumps of unrelated code together. If I can understand what you are trying to do, then you need to model a "has-a" relationship. For example: The Contact Us page is not a html form, it HAS a html form; therefore the instance which creates the Contact Us page is not a html form either, and should not inherit from FormClass; but it should have a FormClass instance it can delegate the creation of the form to. Something like this, perhaps: contact_page_designer = PageDesigner() contact_page_designer.form_designer = FormClass() This can be wrapped inside the __init__ method, of course. The FormClass instance can be passed as a generic argument. Then, your PageDesigner methods which need to create a form simply delegate the work to the form_designer attribute. Instead of this: self.make_form() which depends on self having ten different methods to do with making forms, you do this: self.form_designer.make_form() and all the form-related methods are encapsulated in one place, out of the way. This general technique is known as composition, or delegation, and you use it every time you do something like this: result = self.name.upper() # delegating upper method to the string name And yet, somehow people forget it in favour of inheritance once they move beyond the primitive built-in types. === Code injection === You talk about deciding inheritance at instantiation time, which implies that each instance will get different methods. If so, then so long as you aren't changing dunder methods (double leading and trailing underscore special methods like __init__ and friends), you can inject methods directly onto an instance, either to add new functionality or override existing functionality on a per-instance basis. py> class Parrot: ... def speak(self): ... print "Polly wants a cracker!" ... py> class KillBot: ... def speak(self): ... print "Crush! Kill! Destroy!" ... py> p = Parrot() py> p.speak() Polly wants a cracker! py> p.speak = KillBot().speak py> p.speak() Crush! Kill! Destroy! === Dynamic class creation === Forget about using type(), there's an easier way. def factory(name, parent_class): class MyClass(parent_class): def method(self): print "Called method" return 42 MyClass.__name__ = name return MyClass Much easier than the equivalent using type. def method(self): print "Called method" return 42 type(name, (parent_class,), {'method': method}) -- Steven -- http://mail.python.org/mailman/listinfo/python-list