newbie: copy base class fields

Discussion in 'Python' started by tmp123, May 3, 2007.

  1. tmp123

    tmp123 Guest

    Hello,

    Thanks for your time.

    The following small program gives an error:

    #!/usr/bin/python
    #

    class A:
    def __init__(self):
    self.v1=1

    def __repr__(self):
    return "v1=%d\n" % self.v1

    class B(A):
    def __init__(self,a):
    self=a
    self.v2=2

    def __repr__(self):
    return A.__repr__(self) + ("v2=%d\n" % self.v2)

    x=A()
    print x

    y=B(x)
    print y



    $ ./prueba.pl
    v1=1

    Traceback (most recent call last):
    File "./prueba.pl", line 23, in <module>
    print y
    File "./prueba.pl", line 17, in __repr__
    return A.__repr__(self) + ("v2=%d\n" % self.v2)
    File "./prueba.pl", line 9, in __repr__
    return "v1=%d\n" % self.v1
    AttributeError: B instance has no attribute 'v1'


    It seems that the statement "self=a" is not the correct way to copy
    all the fields of the base class from the __init__ argument to the new
    object.

    Of course, it is not an option to copy one by one all the fields of
    class A inside the __init__ of B.

    Several variants of the program produces similar results.

    Please, could someone explain which way is the correct way?

    Thanks a lot.
    tmp123, May 3, 2007
    #1
    1. Advertising

  2. In <>, tmp123 wrote:

    > The following small program gives an error:
    >
    > #!/usr/bin/python
    > #
    >
    > class A:
    > def __init__(self):
    > self.v1=1
    >
    > def __repr__(self):
    > return "v1=%d\n" % self.v1
    >
    > class B(A):
    > def __init__(self,a):
    > self=a
    > self.v2=2
    >
    > def __repr__(self):
    > return A.__repr__(self) + ("v2=%d\n" % self.v2)
    >
    > x=A()
    > print x
    >
    > y=B(x)
    > print y
    >
    >
    >
    > $ ./prueba.pl
    > v1=1
    >
    > Traceback (most recent call last):
    > File "./prueba.pl", line 23, in <module>
    > print y
    > File "./prueba.pl", line 17, in __repr__
    > return A.__repr__(self) + ("v2=%d\n" % self.v2)
    > File "./prueba.pl", line 9, in __repr__
    > return "v1=%d\n" % self.v1
    > AttributeError: B instance has no attribute 'v1'
    >
    >
    > It seems that the statement "self=a" is not the correct way to copy
    > all the fields of the base class from the __init__ argument to the new
    > object.


    This binds the local name `self` to the same object that is bound to `a`.
    Now you have lost the reference to the instance, so the next line sets the
    attribute `v2` on the object passed to the constructor of the `B` object.

    > Of course, it is not an option to copy one by one all the fields of
    > class A inside the __init__ of B.
    >
    > Several variants of the program produces similar results.
    >
    > Please, could someone explain which way is the correct way?


    Call the `__init__()` of `A`:

    class B(A):
    def __init__(self, a):
    A.__init__(self)
    self.v2 = 2

    Ciao,
    Marc 'BlackJack' Rintsch
    Marc 'BlackJack' Rintsch, May 3, 2007
    #2
    1. Advertising

  3. tmp123

    tmp123 Guest

    On May 3, 4:29 pm, Marc 'BlackJack' Rintsch <> wrote:
    >
    > > #!/usr/bin/python
    > > #

    >
    > > class A:
    > > def __init__(self):
    > > self.v1=1

    >
    > > def __repr__(self):
    > > return "v1=%d\n" % self.v1

    >
    > > class B(A):
    > > def __init__(self,a):
    > > self=a
    > > self.v2=2

    >
    > > def __repr__(self):
    > > return A.__repr__(self) + ("v2=%d\n" % self.v2)

    >
    > > x=A()
    > > print x

    >
    > > y=B(x)
    > > print y

    >
    > > $ ./prueba.pl
    > > v1=1

    >
    > > Traceback (most recent call last):
    > > File "./prueba.pl", line 23, in <module>
    > > print y
    > > File "./prueba.pl", line 17, in __repr__
    > > return A.__repr__(self) + ("v2=%d\n" % self.v2)
    > > File "./prueba.pl", line 9, in __repr__
    > > return "v1=%d\n" % self.v1
    > > AttributeError: B instance has no attribute 'v1'

    >



    Hello Marc,

    Thanks for your help.

    I'm sorry, I've not correctly explained the subject. It is need to
    init class B with the current value of the A instance, not with the
    initial ones. A best example is:

    x=A()
    print x

    x.v1=3

    y=B(x)
    print y

    at the end, y.v1 must be equal to 3.

    Sorry again.
    tmp123, May 3, 2007
    #3
  4. tmp123 <> wrote:
    ...
    > It seems that the statement "self=a" is not the correct way to copy
    > all the fields of the base class from the __init__ argument to the new
    > object.


    Indeed, it isn't. Assigning to self just rebinds the name 'self' as a
    local variable of method B.__init__ -- really useless.

    > Of course, it is not an option to copy one by one all the fields of
    > class A inside the __init__ of B.
    >
    > Several variants of the program produces similar results.
    >
    > Please, could someone explain which way is the correct way?


    Somebody else suggested you call A.__init__ from inside B.__init__, and
    that is correct if what you want to do is "freshly initialize the B
    instance as an A". However, from the fact that you pass to B.__init__
    an argument 'a', it looks as if what you're trying to do is indeed copy
    each of a's instance variables to self (it's hard to read your mind from
    the code you've posted, but if I had to guess that would be by guess),
    where a is an instance of A that's not necessarily "freshly
    initialized".

    In this case, you might for example start B.__init__ with:
    self.__dict__.update(a.__dict__)

    This is not very elegant or solid, but at least it's short and fast:).

    A better way would require having _somewhere_ a list or tuple with the
    names of all the instance variables you know you want to copy; if that
    list of names was for example B._names_to_copy,
    for name in self._names_to_copy:
    value = getattr(a, name)
    setattr(self, name, value)
    IS elegant and robust. The advantages of explicitly controlling what
    names you're copying (rather than blindly taking whatever happens to be
    there) are similar to those of avoiding "from wherever import *": you
    avoid accidental name pollution. The advantages of using getattr and
    setattr (rather than blindly working on the __dict__s) are those of
    working correctly and transparently with properties and other similar
    kinds of descriptors, rather than just "raw" instance variables.


    Alex
    Alex Martelli, May 3, 2007
    #4
  5. tmp123

    Jerry Hill Guest

    On 3 May 2007 07:14:04 -0700, tmp123 <> wrote:
    > Of course, it is not an option to copy one by one all the fields of
    > class A inside the __init__ of B.


    Is it okay to copy them all at once? Like this:

    class B(A):
    def __init__(self, a):
    self.__dict__.update(a.__dict__)
    self.v2 = 2

    That will copy all of the attributes of instance a into the new instance.

    --
    Jerry
    Jerry Hill, May 3, 2007
    #5
  6. tmp123

    tmp123 Guest

    On May 3, 4:57 pm, "Jerry Hill" <> wrote:
    > Is it okay to copy them all at once? Like this:
    >
    > class B(A):
    > def __init__(self, a):
    > self.__dict__.update(a.__dict__)
    > self.v2 = 2
    >


    Thanks a lot for the answers, they seem to agree with the requested
    funcitionality.

    Kind regards.
    tmp123, May 6, 2007
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alf P. Steinbach
    Replies:
    6
    Views:
    531
    John Carson
    Sep 3, 2005
  2. =?ISO-8859-1?Q?Szabolcs_Horv=E1t?=
    Replies:
    4
    Views:
    486
    Daniel T.
    Oct 28, 2006
  3. SzH
    Replies:
    1
    Views:
    342
  4. Victor Bazarov
    Replies:
    15
    Views:
    752
    Greg Comeau
    Mar 4, 2007
  5. middletree

    how to copy from fields to other fields

    middletree, Nov 5, 2003, in forum: ASP General
    Replies:
    1
    Views:
    152
    middletree
    Nov 5, 2003
Loading...

Share This Page