Re: Composition instead of inheritance
On 4/28/2011 1:15 PM, Ethan Furman wrote: For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit/ Comments welcome! ~Ethan~ That looks pretty clever. I tried adding this method to Spam: def test_eggs_02(self): print('testing eggs_02 from spam') and it did just what we wanted. I'm going to have to study this one. Thanks. Alan -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
Ben Finney wrote: Ethan Furman et...@stoneleaf.us writes: Carl Banks wrote: That's not what we mean by composition. Composition is when one object calls upon another object that it owns to implement some of its behavior. Often used to model a part/whole relationship, hence the name. Hmmm. Okay -- any ideas for a better term? Something that describes taking different source classes and fusing them into a new whole, possibly using single-inheritance... Frankenstein, maybe? ;) (Remember that Frankenstein was not the monster, but the scientist.) “Hybrid”? Actualy this story is about the villagers being the monsters :o) JM -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
James Mills wrote: On Fri, Apr 29, 2011 at 11:43 AM, Ethan Furman et...@stoneleaf.us wrote: Hmmm. Okay -- any ideas for a better term? Something that describes taking different source classes and fusing them into a new whole, possibly using single-inheritance... Frankenstein, maybe? ;) I'd have to say that this is typical of MixIns Yes, but it's designed to be used when Mixins fail because of MI issues (see my reply to Carl for an example). Maybe Integrate? ~Ethan~ -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On Thursday, April 28, 2011 6:43:35 PM UTC-7, Ethan Furman wrote: Carl Banks wrote: The sorts of class that this decorator will work for are probably not the ones that are going to have problems cooperating in the first place. So you might as well just use inheritance; that way people trying to read the code will have a common, well-known Python construct rather than a custom decorator to understand. From thread 'python and super' on Python-Dev: Ricardo Kirkner wrote: I'll give you the example I came upon: I have a TestCase class, which inherits from both Django's TestCase and from some custom TestCases that act as mixin classes. So I have something like class MyTestCase(TestCase, Mixin1, Mixin2): ... now django's TestCase class inherits from unittest2.TestCase, which we found was not calling super. This is the type of situation the decorator was written for (although it's too simplistic to handle that exact case, as Ricardo goes on to say he has a setUp in each mixin that needs to be called -- it works fine though if you are not adding duplicate names). The problem is that he was doing mixins wrong. Way wrong. Here is my advice on mixins: Mixins should almost always be listed first in the bases. (The only exception is to work around a technicality. Otherwise mixins go first.) If a mixin defines __init__, it should always accept self, *args and **kwargs (and no other arguments), and pass those on to super().__init__. Same deal with any other function that different sister classes might define in varied ways (such as __call__). A mixin should not accept arguments in __init__. Instead, it should burden the derived class to accept arguments on its behalf, and set attributes before calling super().__init__, which the mixin can access. If you insist on a mixin that accepts arguments in __init__, then it should should pop them off kwargs. Avoid using positional arguments, and never use named arguments. Always go through args and kwargs. If mixins follow these rules, they'll be reasonably safe to use on a variety of classes. (Maybe even safe enough to use in Django classes.) Carl Banks -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
Carl Banks wrote: Here is my advice on mixins: [snip] Cool. Thanks! ~Ethan -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On Fri, Apr 29, 2011 at 3:09 PM, Carl Banks pavlovevide...@gmail.com wrote: Here is my advice on mixins: Mixins should almost always be listed first in the bases. (The only exception is to work around a technicality. Otherwise mixins go first.) If a mixin defines __init__, it should always accept self, *args and **kwargs (and no other arguments), and pass those on to super().__init__. Same deal with any other function that different sister classes might define in varied ways (such as __call__). Really, *any* class that uses super().__init__ should take its arguments and pass them along in this manner. This applies to your base classes as well as your mixins. It's okay to take keyword arguments as well, but you have to be careful to pass them on exactly as you received them. Reason being that you can't pragmatically predict which __init__ method will be invoked next by the super call, which means that you can't predict which arguments will be needed for that call, so you just have to pass all of them along. A mixin should not accept arguments in __init__. Instead, it should burden the derived class to accept arguments on its behalf, and set attributes before calling super().__init__, which the mixin can access. Ugh. This breaks encapsulation, since if I ever need to add an optional argument, I have to add handling for that argument to every derived class that uses that mixin. The mixin should be able to accept new optional arguments without the derived classes needing to know about them. If you insist on a mixin that accepts arguments in __init__, then it should should pop them off kwargs. Avoid using positional arguments, and never use named arguments. Always go through args and kwargs. Theoretically this would break if you had two mixins accepting the same argument, but I can't think of an actual case where that might happen. Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
Ian Kelly wrote: On Thu, Apr 28, 2011 at 11:15 AM, Ethan Furman et...@stoneleaf.us wrote: For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit/ Comments welcome! On line 14, is it intentional that attributes whose values happen to be false are not considered as conflicts? Nope, not intentional at all! I'll fix that... On line 31, this code: thing = getattr(thing, '__func__', None) or thing could be simplified to this: thing = getattr(thing, '__func__', thing) I'll fix that, too. Thanks! -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On Friday, April 29, 2011 2:44:56 PM UTC-7, Ian wrote: On Fri, Apr 29, 2011 at 3:09 PM, Carl Banks wrote: Here is my advice on mixins: Mixins should almost always be listed first in the bases. (The only exception is to work around a technicality. Otherwise mixins go first.) If a mixin defines __init__, it should always accept self, *args and **kwargs (and no other arguments), and pass those on to super().__init__. Same deal with any other function that different sister classes might define in varied ways (such as __call__). Really, *any* class that uses super().__init__ should take its arguments and pass them along in this manner. If you are programming defensively for any possible scenario, you might try this (and you'd still fail). In the real world, certain classes might have more or less probability to be used in a multiple inheritance situations, and programmer needs to weigh the probability of that versus the loss of readability. For me, except when I'm designing a class specifically to participate in MI (such as a mixin), readability wins. [snip] A mixin should not accept arguments in __init__. Instead, it should burden the derived class to accept arguments on its behalf, and set attributes before calling super().__init__, which the mixin can access. Ugh. This breaks encapsulation, since if I ever need to add an optional argument, I have to add handling for that argument to every derived class that uses that mixin. The mixin should be able to accept new optional arguments without the derived classes needing to know about them. Well, encapsulation means nothing to me; if it did I'd be using Java. If you merely mean DRY, then I'd say this doesn't necessarily add to it. The derived class has a responsibility one way or another to get the mixin whatever initializers it needs. Whether it does that with __init__ args or through attributes it still has to do it. Since attributes are more versatile than arguments, and since it's messy to use arguments in MI situations, using attributes is the superior method. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On Fri, Apr 29, 2011 at 5:54 PM, Carl Banks pavlovevide...@gmail.com wrote: Really, *any* class that uses super().__init__ should take its arguments and pass them along in this manner. If you are programming defensively for any possible scenario, you might try this (and you'd still fail). In the real world, certain classes might have more or less probability to be used in a multiple inheritance situations, and programmer needs to weigh the probability of that versus the loss of readability. For me, except when I'm designing a class specifically to participate in MI (such as a mixin), readability wins. Agreed. Actually, my preferred solution is to not use super at all. It's so rarely needed (i.e. diamond inheritance situations) that it's usually not worth it to jump through the hoops it creates, so I prefer to call the base class methods explicitly. For pure base-class + mixin design, you should not have any diamond inheritance situations, so super should not really be necessary. If you merely mean DRY, then I'd say this doesn't necessarily add to it. The derived class has a responsibility one way or another to get the mixin whatever initializers it needs. I mean the difference in terms of maintenance between this: class Derived1(Mixin1, Base): def __init__(self, mixin_arg1, mixin_arg2, *args, **kwargs): self.mixin_arg1 = mixin_arg1 self.mixin_arg2 = mixin_arg2 super(Derived, self).__init__(*args, **kwargs) and simply doing this: class Derived2(Mixin2, Base): def __init__(self, *args, **kwargs): super(Derived, self).__init__(*args, **kwargs) In both cases we are passing the arguments in to the mixin. In the former case, if we later decide to add mixin_arg3, then we have to also add it to the Derived1.__init__ signature and then add a line to set the attribute. In the latter case, adding mixin_arg3 has no effect on the Derived2 initializer at all, because it passes through transparently in the kwargs. Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list
Composition instead of inheritance
For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit/ Comments welcome! ~Ethan~ -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On Thu, Apr 28, 2011 at 11:15 AM, Ethan Furman et...@stoneleaf.us wrote: For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit/ Comments welcome! ~Ethan~ -- http://mail.python.org/mailman/listinfo/python-list That's cool. And if Spam and Eggs were abstract base classes you could register TestAll to them. Granted, that is not so applicable in your example. But generally that would help bridge the inheritance gap for isinstance cases. -eric p.s. I would have commented on the recipe but could not log in... -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
Ethan Furman wrote: For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit/ Comments welcome! ~Ethan~ Sounds great. But I fear that would completely fool any linter. JM -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
Ethan Furman et...@stoneleaf.us writes: For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit/ Comments welcome! It doesn't look like composition at all, though. I understand composition to be the setting of attributes on a class or instance; that recipe doesn't show it very well IMO. -- \ “[The RIAA] have the patience to keep stomping. They're playing | `\ whack-a-mole with an infinite supply of tokens.” —kennon, | _o__) http://kuro5hin.org/ | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On Thursday, April 28, 2011 10:15:02 AM UTC-7, Ethan Furman wrote: For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit/ Comments welcome! That's not what we mean by composition. Composition is when one object calls upon another object that it owns to implement some of its behavior. Often used to model a part/whole relationship, hence the name. The sorts of class that this decorator will work for are probably not the ones that are going to have problems cooperating in the first place. So you might as well just use inheritance; that way people trying to read the code will have a common, well-known Python construct rather than a custom decorator to understand. If you want to enforce no duplication of attributes you can do that, such as with this untested metaclass: class MakeSureNoBasesHaveTheSameClassAttributesMetaclass(type): def __new__(metatype,name,bases,dct): u = collections.Counter() for base in bases: for key in base.__dict__.keys(): u[key] += 1 for key in dct.keys(): u[key] += 1 if any(u[key] 1 for key in u.keys()): raise TypeError(base classes and this class share some class attributes) return type.__new__(metatype,name,bases,dct) Carl Banks -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
Carl Banks wrote: That's not what we mean by composition. Composition is when one object calls upon another object that it owns to implement some of its behavior. Often used to model a part/whole relationship, hence the name. Hmmm. Okay -- any ideas for a better term? Something that describes taking different source classes and fusing them into a new whole, possibly using single-inheritance... Frankenstein, maybe? ;) The sorts of class that this decorator will work for are probably not the ones that are going to have problems cooperating in the first place. So you might as well just use inheritance; that way people trying to read the code will have a common, well-known Python construct rather than a custom decorator to understand. From thread 'python and super' on Python-Dev: Ricardo Kirkner wrote: I'll give you the example I came upon: I have a TestCase class, which inherits from both Django's TestCase and from some custom TestCases that act as mixin classes. So I have something like class MyTestCase(TestCase, Mixin1, Mixin2): ... now django's TestCase class inherits from unittest2.TestCase, which we found was not calling super. This is the type of situation the decorator was written for (although it's too simplistic to handle that exact case, as Ricardo goes on to say he has a setUp in each mixin that needs to be called -- it works fine though if you are not adding duplicate names). ~Ethan~ -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On 29/04/2011 02:43, Ethan Furman wrote: Carl Banks wrote: That's not what we mean by composition. Composition is when one object calls upon another object that it owns to implement some of its behavior. Often used to model a part/whole relationship, hence the name. Hmmm. Okay -- any ideas for a better term? Something that describes taking different source classes and fusing them into a new whole, possibly using single-inheritance... Frankenstein, maybe? ;) [snip] Fusing/fusion? Compounding? -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On Thu, 28 Apr 2011 15:35:47 -0700, Carl Banks wrote: On Thursday, April 28, 2011 10:15:02 AM UTC-7, Ethan Furman wrote: For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes- instead-of-multiple-inherit/ Comments welcome! That's not what we mean by composition. Composition is when one object calls upon another object that it owns to implement some of its behavior. I thought that was delegation. As in, when one object delegates some or all of it's behaviour to another object: http://code.activestate.com/recipes/52295 Often used to model a part/whole relationship, hence the name. In mathematics, composition means to make a function by applying a function to the output of another. E.g.: f o g(x) is equivalent to f(g(x)) (Strictly speaking, the o in the f o g should be a little circle rather than lowercase O.) -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On Fri, Apr 29, 2011 at 11:43 AM, Ethan Furman et...@stoneleaf.us wrote: Hmmm. Okay -- any ideas for a better term? Something that describes taking different source classes and fusing them into a new whole, possibly using single-inheritance... Frankenstein, maybe? ;) I'd have to say that this is typical of MixIns cheers James -- -- James Mills -- -- Problems are solved by method -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
Ethan Furman et...@stoneleaf.us writes: Carl Banks wrote: That's not what we mean by composition. Composition is when one object calls upon another object that it owns to implement some of its behavior. Often used to model a part/whole relationship, hence the name. Hmmm. Okay -- any ideas for a better term? Something that describes taking different source classes and fusing them into a new whole, possibly using single-inheritance... Frankenstein, maybe? ;) (Remember that Frankenstein was not the monster, but the scientist.) “Hybrid”? -- \ “If sharing a thing in no way diminishes it, it is not rightly | `\ owned if it is not shared.” —Augustine of Hippo (354–430 CE) | _o__) | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
Steven D'Aprano steve+comp.lang.pyt...@pearwood.info writes: On Thu, 28 Apr 2011 15:35:47 -0700, Carl Banks wrote: That's not what we mean by composition. Composition is when one object calls upon another object that it owns to implement some of its behavior. I thought that was delegation. As in, when one object delegates some or all of it's behaviour to another object: http://code.activestate.com/recipes/52295 The difference being that, with delegation, the object being called is unrelated to this one. With composition, the object being called is not wholly separate, but is instead an attribute on the current object. The “another object that it owns” was, I presume, meant to communicate this “an object which is an attribute of the current one” relationship. In mathematics, composition means to make a function by applying a function to the output of another. The term “composition” in the programming sense comes from OO design, not functional nor mathematical terminology. -- \ “I don't like country music, but I don't mean to denigrate | `\ those who do. And for the people who like country music, | _o__)denigrate means ‘put down’.” —Bob Newhart | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On Thu, Apr 28, 2011 at 3:35 PM, Carl Banks pavlovevide...@gmail.com wrote: On Thursday, April 28, 2011 10:15:02 AM UTC-7, Ethan Furman wrote: For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit/ Comments welcome! That's not what we mean by composition. Composition is when one object calls upon another object that it owns to implement some of its behavior. Often used to model a part/whole relationship, hence the name. It's a pretty old idea, that seems to be getting revived in a big way all of a sudden. Perhaps the Java people just rediscovered it? In a Software Engineering class using Ada, the teacher called it Structural Inclusion, and of course it was an important concept in Ada, because Ada had no inheritance. This was in 1989-1990. -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
Dan Stromberg drsali...@gmail.com writes: On Thu, Apr 28, 2011 at 3:35 PM, Carl Banks pavlovevide...@gmail.com wrote: That's not what we mean by composition. Composition is when one object calls upon another object that it owns to implement some of its behavior. Often used to model a part/whole relationship, hence the name. It's a pretty old idea, that seems to be getting revived in a big way all of a sudden. Perhaps the Java people just rediscovered it? I think it's more that people keep re-discovering how irredeemably messy multiple inheritance is, and finding that object composition is better in most cases :-) -- \ “There's a fine line between fishing and standing on the shore | `\looking like an idiot.” —Steven Wright | _o__) | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On Thu, Apr 28, 2011 at 11:15 AM, Ethan Furman et...@stoneleaf.us wrote: For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit/ Comments welcome! On line 14, is it intentional that attributes whose values happen to be false are not considered as conflicts? On line 31, this code: thing = getattr(thing, '__func__', None) or thing could be simplified to this: thing = getattr(thing, '__func__', thing) Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list
Re: Composition instead of inheritance
On 4/28/2011 3:35 PM, Carl Banks wrote: On Thursday, April 28, 2011 10:15:02 AM UTC-7, Ethan Furman wrote: For anybody interested in composition instead of multiple inheritance, I have posted this recipe on ActiveState (for python 2.6/7, not 3.x): http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit/ Comments welcome! That's not what we mean by composition. Composition is when one object calls upon another object that it owns to implement some of its behavior. Often used to model a part/whole relationship, hence the name. The distinction isn't that strong in Python, where an object can't be part of another object. Object fields are references, not the objects themselves. In C++, you really can have an object as a field of an enclosing object. The inner object's destructor will be called first. Destructors and ownership tend not to be too important in Python, because storage management is automatic. John Nagle -- http://mail.python.org/mailman/listinfo/python-list