mixin class

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Udo Gleich

    mixin class

    Hi,

    I try to implement mixin classes. Thats why I
    need to make a new class at runtime.

    --tmp.py-------------------------------------

    import new

    class K1(object):
    pass

    class K2(object):
    pass

    mixed = new.classobj("K 1_K2", (K1, K1), {})
    new_instance = new.instance(mi xed, {})

    print new_instance

    ---------------------------------------------

    Making a new instance from the new class works
    only if K1 is not derived from object. If I use
    new style classes I get the following traceback:

    Traceback (most recent call last):
    File "tmp.py", line 10, in ?
    new_instance = new.instance(mi xed, {})
    TypeError: instance() argument 1 must be class, not type

    I use Python 2.2.3 and Win2000.

    My question: How do I implement mixin classes
    with new style classes?

    Thanks,

    Udo



  • Michele Simionato

    #2
    Re: mixin class

    Udo Gleich <udo.gleich@web .de> wrote in message news:<3F24F8D2. E1ADFB08@web.de >...[color=blue]
    > Hi,
    >
    > I try to implement mixin classes. Thats why I
    > need to make a new class at runtime.
    >
    > --tmp.py-------------------------------------
    >
    > import new
    >
    > class K1(object):
    > pass
    >
    > class K2(object):
    > pass
    >
    > mixed = new.classobj("K 1_K2", (K1, K1), {})
    > new_instance = new.instance(mi xed, {})
    >
    > print new_instance
    >
    > ---------------------------------------------
    >
    > Making a new instance from the new class works
    > only if K1 is not derived from object. If I use
    > new style classes I get the following traceback:
    >
    > Traceback (most recent call last):
    > File "tmp.py", line 10, in ?
    > new_instance = new.instance(mi xed, {})
    > TypeError: instance() argument 1 must be class, not type
    >
    > I use Python 2.2.3 and Win2000.
    >
    > My question: How do I implement mixin classes
    > with new style classes?
    >
    > Thanks,
    >
    > Udo[/color]

    Why not simply

    class K1(object):
    pass

    class K2(object):
    pass

    mixed = type("K1_K2", (K1, K1), {})
    new_instance = mixed()

    print new_instance

    ?

    "type" is described in http://www.python.org/2.2.3/descrintro.html
    (in one line very easy to miss ;)


    Michele

    Comment

    • Udo Gleich

      #3
      Re: mixin class

      Hi,
      [color=blue]
      > Why not simply
      >
      > class K1(object):
      > pass
      >
      > class K2(object):
      > pass
      >
      > mixed = type("K1_K2", (K1, K1), {})
      > new_instance = mixed()
      >
      > print new_instance
      >[/color]

      almost.

      If K1 has a constructor that takes arguments you get an
      error when you call the constructor of the derived class
      without an argument. Why do I want to do that? Usually
      one would say that I should know the arguments of the
      constructor of the derived class.

      What I want to do is take *two objects*, derive from both
      their classes, make a new object and combine the state of
      the old objects.

      I dont know if that is a good idea. I would appreciate comments
      on the following solution. Especially the use of the dummy_init
      function as an empty constructor looks not quite right to me.

      ---------------------------------------------------------------------

      def dummy_init(self ):
      pass

      class Mixin:

      __shared_state = {"classes":{ }}

      def __init__(self):
      self.__dict__ = self.__shared_s tate

      def mix(self, original_instan ce, mixin_instance) :
      original_class = original_instan ce.__class__
      mixin_class = mixin_instance. __class__
      name = original_class. __name__ + '_' + mixin_class.__n ame__
      mixed = self.classes.ge t(name,
      type(name,
      (mixin_class, original_class) ,
      {"__init__": dummy_init}))
      new_instance = mixed()

      new_instance.__ dict__.update(m ixin_instance._ _dict__)
      new_instance.__ dict__.update(o riginal_instanc e.__dict__)

      try:
      new_instance.la te_init_origina l()
      except AttributeError:
      pass
      try:
      new_instance.la te_init_mixin()
      except AttributeError:
      pass
      return new_instance

      class K1(object):
      def __init__(self, a):
      self.a = a

      class K2(object):
      def late_init_mixin (self):
      self.b = self.a + 1


      mixer = Mixin()

      new_instance = mixer.mix(K1(3) , K2())

      print new_instance
      print new_instance.a, new_instance.b

      -------------------------------------------------------------------------

      Comment

      • Udo Gleich

        #4
        Re: mixin class

        > > mixed = new.classobj("K 1_K2", (K1, K1), {})

        There is an error in the code. Obviously it should
        read

        mixed = new.classobj("K 1_K2", (K1, K2), {})
        --

        Comment

        • Michele Simionato

          #5
          Re: mixin class

          Udo Gleich <udo.gleich@web .de> wrote in message news:<3F262A67. 57E4762C@web.de >...[color=blue]
          > What I want to do is take *two objects*, derive from both
          > their classes, make a new object and combine the state of
          > the old objects.
          >
          > I dont know if that is a good idea. I would appreciate comments
          > on the following solution. Especially the use of the dummy_init
          > function as an empty constructor looks not quite right to me.[/color]

          You may avoid dummy_init and have the default object.__init__ but
          this is not the point. The whole construction seems ugly to me.
          Do you have the option of using only class variables ? I mean, no
          explicit instance dictionary? Then you could simply create the
          mixin from the original classes and not merge by hand the
          instance dictionaries. Do you have the option of modifying the
          original classes to make the all structure more multiple inheritance
          friendly? The idea is that one should derive objects from classes,
          not classes from objects. What you are doing will probably work,
          but It is quite ugly to me.I cannot say more if I have no idea of what
          are your constraints. If you cannot touch the original classes,
          remember that you can create modifications of them, as mixin-frendly
          as you wish. I also have a question: why don't you override the
          __init__ method in M in such a way that it calls K1.__init__ and
          K2.__init__ according to the number of arguments? That would be
          the first thing would come to my mind, but maybe you have reasons
          why you don't want that.
          HTH,


          Michele

          Comment

          • Jeremy Bowers

            #6
            Re: mixin class

            On Mon, 28 Jul 2003 12:20:02 +0200, Udo Gleich wrote:[color=blue]
            > My question: How do I implement mixin classes
            > with new style classes?[/color]

            Um, if I understand what you're trying to do correctly, it's easy:

            --------------
            import random

            class A(object): pass
            class B(object): pass
            class C(object): pass
            class D(object): pass

            mixin = random.choice([C, D])

            class A_B_and_C_or_D( A, B, mixin): pass

            newName = A_B_and_C_or_D

            newInstance = newName()
            ----------------

            (Warning: Didn't actually type this in)

            The classes being derived from can be variable; in fact I do this rather
            too frequently for my own good, perhaps. (I tend to use it for class I
            want to be intimately involved with each other, but also usable
            separately, having one of them dynamically derive from either object or
            the other class, depending on whether the other class is available.)

            So in this example, on any given run, class A_B_and_C_or_D will always
            derive from A and B, and may derive from either of C or D.

            You can dynamically do this in a loop or something if you're feeling
            creative, if you assign the class to new names, as I did here for
            "newName". AFAIK there's no way to programmaticall y create new classes
            with generated names without resorting to eval (bad idea), but you can
            bind them to new names after creation and that works OK.

            ----------------

            classesILike = {}
            for i in range(10):
            class tmp(object): pass
            classesILIke[i] = tmp

            ----------------

            and of course "tmp" may derive from what it will.

            The inheritance list is as dynamic as anything else in Python; feel free
            to use it that way. Personally I find this is a "killer feature"... you'd
            find it hard to describe in advance when you'd want it, but when
            you want it, you want it ***badly***, because the kludge will be a
            killer... and there are very, very few languages that can do this cleanly
            (and still share Python's other benefits).

            Comment

            Working...