converting base class instance to derived class instance

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Sridhar R

    converting base class instance to derived class instance

    Consider the code below,

    class Base(object):
    pass

    class Derived(object) :

    def __new__(cls, *args, **kwds):
    # some_factory returns an instance of Base
    # and I have to derive from this instance!
    inst = some_factory() # this returns instance of Base
    return inst # Oops! this isn't an instance of Derived

    def __init__(self):
    # This won't be called as __new__ returns Base's instance
    pass

    The constrait is there is some factory function that creates an
    instance of Base class. So I _can't_ call "Base.__init__( self)" in
    Derived.__init_ _ func, as their will be _two_ instances (one created
    by Derived.__init_ _ and other created by the factory function)

    Simply I want to get a derived class object, but instead of allowing
    _automatic_ creation of Base instance, I want to use _existing_ Base's
    instance, then use this as a Derived's instance.

    Will metaclass solve this problem?
  • Peter Otten

    #2
    Re: converting base class instance to derived class instance

    Sridhar R wrote:
    [color=blue]
    > Consider the code below,
    >
    > class Base(object):
    > pass
    >
    > class Derived(object) :[/color]

    I suppose that should be

    class Derived(Base):[color=blue]
    >
    > def __new__(cls, *args, **kwds):
    > # some_factory returns an instance of Base
    > # and I have to derive from this instance!
    > inst = some_factory() # this returns instance of Base[/color]

    # using brute force:
    inst.__class__ = Derived

    No guarantees, but the above seems to work.
    [color=blue]
    > return inst # Oops! this isn't an instance of Derived
    >
    > def __init__(self):
    > # This won't be called as __new__ returns Base's instance
    > pass
    >
    > The constrait is there is some factory function that creates an
    > instance of Base class. So I _can't_ call "Base.__init__( self)" in
    > Derived.__init_ _ func, as their will be _two_ instances (one created
    > by Derived.__init_ _ and other created by the factory function)[/color]

    As some_factory() returns an already initialized instance of Base, there
    should be no need to call it again from inside Derived.__init_ _()
    [color=blue]
    > Simply I want to get a derived class object, but instead of allowing
    > _automatic_ creation of Base instance, I want to use _existing_ Base's
    > instance, then use this as a Derived's instance.
    >
    > Will metaclass solve this problem?[/color]

    I think metaclasses will solve only metaproblems...

    Skeptically yours,
    Peter

    Comment

    • John Roth

      #3
      Re: converting base class instance to derived class instance


      "Sridhar R" <sridharinfinit y@yahoo.com> wrote in message
      news:930ba99a.0 401200413.5fae6 fb9@posting.goo gle.com...[color=blue]
      > Consider the code below,
      >
      > class Base(object):
      > pass
      >
      > class Derived(object) :
      >
      > def __new__(cls, *args, **kwds):
      > # some_factory returns an instance of Base
      > # and I have to derive from this instance!
      > inst = some_factory() # this returns instance of Base
      > return inst # Oops! this isn't an instance of Derived
      >
      > def __init__(self):
      > # This won't be called as __new__ returns Base's instance
      > pass[/color]

      __new__ can return an instance of any class it pleases.
      It's not restricted to returning an instance of the class it
      happens to be in, nor is it restricted to returning a newly
      created instance, for that matter. It can do the entire
      construction job without using the __init__ method.

      However, I don't think that's the best solution. If
      your factory is going to return instances of several
      different classes, I think it's best that it be an explicit
      factory method or function, not something that magically
      happens in a class constructor. I'd rather not have to
      deal with programs where class constructors pass me
      instances of classes other than the one I'm calling.

      If you want to do a little bit of deep magic, a factory
      function can create an instance by calling object(),
      plug in whatever attributes it wants and then change the
      __class__ attribute to whatever class it wants before
      it returns the newly minted instance. It doesn't have to
      go near anything that resembles a constructor (other than
      calling object() to get a new instance, of course.)
      [color=blue]
      > The constraint is there is some factory function that creates an
      > instance of Base class. So I _can't_ call "Base.__init__( self)" in
      > Derived.__init_ _ func, as their will be _two_ instances (one created
      > by Derived.__init_ _ and other created by the factory function)
      >
      > Simply I want to get a derived class object, but instead of allowing
      > _automatic_ creation of Base instance, I want to use _existing_ Base's
      > instance, then use this as a Derived's instance.
      >
      > Will metaclass solve this problem?[/color]

      Wrong tool. Metaclasses are used to set up classes, not to
      set up instances.

      John Roth


      Comment

      • Michele Simionato

        #4
        Re: converting base class instance to derived class instance

        sridharinfinity @yahoo.com (Sridhar R) wrote in message news:<930ba99a. 0401200413.5fae 6fb9@posting.go ogle.com>...[color=blue]
        > Consider the code below,
        >
        > class Base(object):
        > pass
        >
        > class Derived(object) :
        >
        > def __new__(cls, *args, **kwds):
        > # some_factory returns an instance of Base
        > # and I have to derive from this instance!
        > inst = some_factory() # this returns instance of Base
        > return inst # Oops! this isn't an instance of Derived
        >
        > def __init__(self):
        > # This won't be called as __new__ returns Base's instance
        > pass
        >
        > The constrait is there is some factory function that creates an
        > instance of Base class. So I _can't_ call "Base.__init__( self)" in
        > Derived.__init_ _ func, as their will be _two_ instances (one created
        > by Derived.__init_ _ and other created by the factory function)
        >
        > Simply I want to get a derived class object, but instead of allowing
        > _automatic_ creation of Base instance, I want to use _existing_ Base's
        > instance, then use this as a Derived's instance.
        >
        > Will metaclass solve this problem?[/color]

        I don't really understand what you want to do (i.e. do you want
        Derived.__init_ _ to be called or not?). Moreover, as others pointed
        out, it is cleaner to use a class factory than to pervert __new__.
        If you really want to use a metaclass, you could override the
        __call__ method of the metaclass, in such a way to interfer with the
        class instantiation. For instance, this is the code to make a singleton
        class (which is a FAQ ;)

        class Singleton(type) :
        "Instances of this metaclass are singletons"
        def __init__(cls,na me,bases,dic):
        super(Singleton ,cls).__init__( name,bases,dic)
        cls.instance=No ne
        def __call__(cls,*a rgs,**kw):
        if cls.instance is None:
        cls.instance=su per(Singleton,c ls).__call__(*a rgs,**kw)
        return cls.instance

        class C:
        __metaclass__=S ingleton

        This is not what you want but you can play with __call__ and get
        the behavior you want. Still, why don't just use a simple factory?

        Michele Simionato

        Comment

        • François Pinard

          #5
          Re: converting base class instance to derived class instance

          [John Roth]
          [color=blue]
          > If you want to do a little bit of deep magic, a factory function can
          > create an instance by calling object(), plug in whatever attributes
          > it wants and then change the __class__ attribute to whatever class it
          > wants before it returns the newly minted instance. It doesn't have
          > to go near anything that resembles a constructor (other than calling
          > object() to get a new instance, of course.)[/color]

          Hello, John, and gang! :-)

          How one does that? I'm merely curious. Using Python 2.3.3, the result
          of `object()' does not have a `__dict__', and seemingly may not be given
          a `__dict__' either. See:


          Python 2.3.3 (#1, Jan 24 2004, 09:01:30)
          [GCC 3.3 20030226 (prerelease) (SuSE Linux)] on linux2
          Type "help", "copyright" , "credits" or "license" for more information.
          from __future__ import division[color=blue][color=green][color=darkred]
          >>> from __future__ import division
          >>> o = object()
          >>> o.__dict__[/color][/color][/color]
          Traceback (most recent call last):
          File "<stdin>", line 1, in ?
          AttributeError: 'object' object has no attribute '__dict__'[color=blue][color=green][color=darkred]
          >>> o.__dict__ = {}[/color][/color][/color]
          Traceback (most recent call last):
          File "<stdin>", line 1, in ?
          AttributeError: 'object' object has no attribute '__dict__'[color=blue][color=green][color=darkred]
          >>> class C(object): pass[/color][/color][/color]
          .... [color=blue][color=green][color=darkred]
          >>> o.__class__ = C[/color][/color][/color]
          Traceback (most recent call last):
          File "<stdin>", line 1, in ?
          TypeError: __class__ assignment: only for heap types[color=blue][color=green][color=darkred]
          >>> [/color][/color][/color]


          By the way, what is a "heap type"?

          --
          François Pinard http://www.iro.umontreal.ca/~pinard

          Comment

          • John Roth

            #6
            Re: converting base class instance to derived class instance


            "François Pinard" <pinard@iro.umo ntreal.ca> wrote in message
            news:mailman.13 72.1076344361.1 2720.python-list@python.org ...
            [John Roth]
            [color=blue]
            > If you want to do a little bit of deep magic, a factory function can
            > create an instance by calling object(), plug in whatever attributes
            > it wants and then change the __class__ attribute to whatever class it
            > wants before it returns the newly minted instance. It doesn't have
            > to go near anything that resembles a constructor (other than calling
            > object() to get a new instance, of course.)[/color]

            Hello, John, and gang! :-)

            How one does that? I'm merely curious. Using Python 2.3.3, the result
            of `object()' does not have a `__dict__', and seemingly may not be given
            a `__dict__' either. See:

            [John's answer]
            My goof. The correct call is:

            object.__new__( klas)

            where klas is the class object you want
            the instance constructed for.


            John Roth


            --
            François Pinard http://www.iro.umontreal.ca/~pinard


            Comment

            • Gerrit

              #7
              Re: converting base class instance to derived class instance

              Fran�ois Pinard wrote:[color=blue]
              > By the way, what is a "heap type"?[/color]

              I don't know, but:



              heap

              1. <programming> An area of memory used for dynamic memory allocation
              where blocks of memory are allocated and freed in an arbitrary order and
              the pattern of allocation and size of blocks is not known until run
              time. Typically, a program has one heap which it may use for several
              different purposes.

              Heap is required by languages in which functions can return arbitrary
              data structures or functions with free variables (see closure). In C
              functions malloc and free provide access to the heap.

              Contrast stack. See also dangling pointer.

              2. <programming> A data structure with its elements partially ordered
              (sorted) such that finding either the minimum or the maximum (but not
              both) of the elements is computationally inexpensive (independent of the
              number of elements), while both adding a new item and finding each
              subsequent smallest/largest element can be done in O(log n) time, where
              n is the number of elements.

              Formally, a heap is a binary tree with a key in each node, such that all
              the leaves of the tree are on two adjacent levels; all leaves on the
              lowest level occur to the left and all levels, except possibly the
              lowest, are filled; and the key in the root is at least as large as the
              keys in its children (if any), and the left and right subtrees (if they
              exist) are again heaps.

              Note that the last condition assumes that the goal is finding the
              minimum quickly.

              Heaps are often implemented as one-dimensional arrays. Still assuming
              that the goal is finding the minimum quickly the invariant is

              heap[i] <= heap[2*i] and heap[i] <= heap[2*i+1] for all i,


              where heap[i] denotes the i-th element, heap[1] being the first.
              Heaps can be used to implement priority queues or in sort algorithms.


              And:


              Heaps are arrays for which heap[k] <= heap[2*k+1] and heap[k] <=
              heap[2*k+2] for all k, counting elements from zero. For the sake of
              comparison, non-existing elements are considered to be infinite. The
              interesting property of a heap is that heap[0] is always its smallest
              element.

              Gerrit.

              --
              PrePEP: Builtin path type

              Asperger's Syndrome - a personal approach:


              Comment

              • François Pinard

                #8
                Re: converting base class instance to derived class instance

                [John Roth]
                [color=blue][color=green]
                > > If you want to do a little bit of deep magic, a factory function can
                > > create an instance by calling object(), [...] My goof. The correct
                > > call is: object.__new__( klas) [...][/color][/color]

                OK, thanks. `object.__new__ ' is what I was using already. It was
                looking kosher to me because of the explanations in `descrintro'. Maybe
                I was seduced and tempted by the announced bit of deep magic, and was
                trying to rediscover the secret. My little Harry Potter side! :-)

                --
                François Pinard http://www.iro.umontreal.ca/~pinard

                Comment

                • François Pinard

                  #9
                  Re: converting base class instance to derived class instance

                  [Gerrit][color=blue]
                  > [François Pinard][color=green]
                  > > By the way, what is a "heap type"?[/color][/color]
                  [color=blue]
                  > http://foldoc.doc.ic.ac.uk heap [...] 1. An area of memory [...]
                  > 2. A data structure [...][/color]

                  Wow, Gerrit, I appreciate your effort in providing this comprehensive
                  answer (and am saving the reference to `foldoc', which looks useful).
                  My question was likely ambiguous, sorry. Reading "heap type" in an
                  article written in the context of Python new-style classes, I wondered
                  if "heap type" did not refer to some classification of Python types
                  which I did not know, but should know.
                  [color=blue]
                  > http://www.python.org/dev/doc/devel/...ule-heapq.html[/color]

                  If you follow the `Theory' link from the page above, you might see that
                  I wrote this explanation. The editor was kind above to push my name in
                  there :-). Not really that I expected it, it even surprised me. On the
                  other hand, it officialises a tiny bit the fact that I much like Python!

                  --
                  François Pinard http://www.iro.umontreal.ca/~pinard

                  Comment

                  • John Roth

                    #10
                    Re: converting base class instance to derived class instance


                    "François Pinard" <pinard@iro.umo ntreal.ca> wrote in message
                    news:mailman.13 72.1076344361.1 2720.python-list@python.org ...
                    [color=blue][color=green][color=darkred]
                    >>> o.__class__ = C[/color][/color][/color]
                    Traceback (most recent call last):
                    File "<stdin>", line 1, in ?
                    TypeError: __class__ assignment: only for heap types


                    By the way, what is a "heap type"?


                    I think they're refering to objects that are allocated
                    on the heap. I'm not sure what attempting to
                    instantiate object would do, but I suspect the result
                    would be a built-in that can't be modified.

                    John Roth[color=blue][color=green][color=darkred]
                    >>>[/color][/color][/color]


                    --
                    François Pinard http://www.iro.umontreal.ca/~pinard


                    Comment

                    • François Pinard

                      #11
                      Re: converting base class instance to derived class instance

                      [John Roth][color=blue]
                      > [François Pinard][/color]
                      [color=blue][color=green][color=darkred]
                      > > >>> o.__class__ = C[/color]
                      > > Traceback (most recent call last):
                      > > File "<stdin>", line 1, in ?
                      > > TypeError: __class__ assignment: only for heap types[/color]
                      > [color=green]
                      > > By the way, what is a "heap type"?[/color][/color]
                      [color=blue]
                      > I think they're refering to objects that are allocated on the
                      > heap. I'm not sure what attempting to instantiate object would do, but
                      > I suspect the result would be a built-in that can't be modified.[/color]

                      Someone suggested, on this list, that `object()' could be used for
                      cheaply producing an object which is guaranteed unique, when there is no
                      need for that object to have any other property.

                      If you do:

                      a = object()
                      b = object()
                      c = object()
                      ...

                      you will observe that they are all different, none of `a', `b', `c'
                      compare with `is' to another. I do not see how the result could be
                      built-in or pre-allocated.

                      I could understand that some immutable objects, like 0, "z" or () could
                      be allocated statically. But for `object()', I do not see.

                      --
                      François Pinard http://www.iro.umontreal.ca/~pinard

                      Comment

                      • Michele Simionato

                        #12
                        Re: converting base class instance to derived class instance

                        François Pinard <pinard@iro.umo ntreal.ca> wrote in message news:<mailman.1 372.1076344361. 12720.python-list@python.org >...[color=blue]
                        > By the way, what is a "heap type"?[/color]

                        More or less, an user defined type, as opposed to a builtin type:


                        Comment

                        • John Roth

                          #13
                          Re: converting base class instance to derived class instance


                          "François Pinard" <pinard@iro.umo ntreal.ca> wrote in message
                          news:mailman.13 90.1076365471.1 2720.python-list@python.org ...
                          [John Roth][color=blue]
                          > [François Pinard][/color]
                          [color=blue][color=green][color=darkred]
                          > > >>> o.__class__ = C[/color]
                          > > Traceback (most recent call last):
                          > > File "<stdin>", line 1, in ?
                          > > TypeError: __class__ assignment: only for heap types[/color]
                          >[color=green]
                          > > By the way, what is a "heap type"?[/color][/color]
                          [color=blue]
                          > I think they're refering to objects that are allocated on the
                          > heap. I'm not sure what attempting to instantiate object would do, but
                          > I suspect the result would be a built-in that can't be modified.[/color]

                          Someone suggested, on this list, that `object()' could be used for
                          cheaply producing an object which is guaranteed unique, when there is no
                          need for that object to have any other property.

                          If you do:

                          a = object()
                          b = object()
                          c = object()
                          ...

                          you will observe that they are all different, none of `a', `b', `c'
                          compare with `is' to another. I do not see how the result could be
                          built-in or pre-allocated.

                          I could understand that some immutable objects, like 0, "z" or () could
                          be allocated statically. But for `object()', I do not see.

                          [John Roth]
                          But I believe that object itself is a built-in type, and the error
                          message in question specified "heap TYPE".

                          John Roth

                          --
                          François Pinard http://www.iro.umontreal.ca/~pinard


                          Comment

                          • François Pinard

                            #14
                            Re: converting base class instance to derived class instance

                            [Michele Simionato][color=blue]
                            > François Pinard <pinard@iro.umo ntreal.ca> wrote in message news:<mailman.1 372.1076344361. 12720.python-list@python.org >...[color=green]
                            > > By the way, what is a "heap type"?[/color][/color]
                            [color=blue]
                            > More or less, an user defined type, as opposed to a builtin type:[/color]
                            [color=blue]
                            > http://groups.google.it/groups?hl=it....lang.python.*[/color]

                            That sequence of articles was instructive, thanks!

                            Maybe the Python documentation should be amended, somewhere, somehow, so
                            the expression "heap type" is explained. Or maybe it is already and I
                            just did not find it. The fact is that it is used in a diagnostic.

                            --
                            François Pinard http://www.iro.umontreal.ca/~pinard

                            Comment

                            • François Pinard

                              #15
                              Re: converting base class instance to derived class instance

                              [John Roth]
                              [color=blue]
                              > But I believe that object itself is a built-in type, and the error
                              > message in question specified "heap TYPE".[/color]

                              I understand what you say, and it sounds logical. Thanks!

                              --
                              François Pinard http://www.iro.umontreal.ca/~pinard

                              Comment

                              Working...