Simple metaclass code failing

LittleGrasshopper seattlehanks at yahoo.com
Tue Jun 2 01:14:05 CEST 2009


On Jun 1, 3:44 am, Piet van Oostrum <p... at cs.uu.nl> wrote:
> >>>>> Piet van Oostrum <p... at cs.uu.nl> (I) wrote:
> >I> But your class definition:
> >I> class C3(C1, C2):
> >I> says that C1 should be before C2. Conflict!!
> >I> Change it to class C3(C2, C1):
>
> Of course the C1 is then superfluous.
>
> I wonder why you want this. What is the problem you want to solve?
>
> Apart from the metaclasses (that you still can use with `class C3(C2)')
> I could think of the following use case:
>
> class C1(object):
>       def m1(self):
>           return 'C1.m1'
>
> class C2(C1):
>       # override m1
>       def m1(self):
>           return 'C2.m1'
>       def m2(self):
>           return 'C2.m2'+self.m1()
>
> class C3(C1, C2):
>       def test(self):
>           print self.m1()+self.m2()
>
> i.e. in C3 we `ignore' the override of m1 in C2 but still want to make
> use of the m2 from C2.
>
> The question that arises then is: the self.m1() inside m2, which m1
> should it use? For an instance of C3 it would use C1.m1, but for an
> instance of C2 it would use C2.m2.
>
> However, every instance of C3 can also be considered an instance of C2,
> (Liskov substitution principle), therefore there is a conflict. That is
> exactly the conflict that the MRO signals.
>
> If you want that kind of behaviour it can be solved by using a mixin
> class for the m2 method:
>
> class C1(object):
>      __metaclass__ = M1
>      def m1(self):
>          return 'C1.m1'
> class Cmix(object):
>      def m2(self):
>          return 'C2.m2'+self.m1()
> class C2(C1, Cmix):
>      __metaclass__ = M2
>      # override m1
>      def m1(self):
>          return 'C2.m1'
> class C3(C1, Cmix):
>      __metaclass__ = M3
>      def test(self):
>          print self.m1()+self.m2()
>
> --
> Piet van Oostrum <p... at cs.uu.nl>
> URL:http://pietvanoostrum.com[PGP 8DAE142BE17999C4]
> Private email: p... at vanoostrum.org

Your discussion of this scenario, why it justifiably fails, and the
alternative solution using a mixing, is all excellent. I am going to
keep this for future reference. I am at a stage of my Python journey
that some of these things seem rather mysterious, so I especially
appreciate this very detailed discussion.

To answer your question, I actually got this hierarchy directly from
Guido's paper on class unification that came out with 2.2.3.



More information about the Python-list mailing list