how to copy a Python object

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • mitsura@skynet.be

    #1

    how to copy a Python object

    Hi,

    I am new to Python and OO programming.
    I need to copy a Python object (of a class I made myself).
    new_obj = old_object doesn't seem to work since apparently new_obj is
    then a referrence to old_obj.

    I found out that there is a module called 'copy' that allows you to do
    a shallow or a deep copy.
    I need a deep copy since my object contains dicts to other objects that
    also need to be copied.

    However, when I do new_object = copy.deepcopy(o ld_object) I get a
    series of errors. The most important one:
    "
    TypeError: object.__new__( PySwigObject) is not safe, use
    PySwigObject.__ new__()
    "

    So any help much appreciated.

    With kind regards,

    Kris

    I am using Python 2.4

  • aurelien.campeas@free.fr

    #2
    Re: how to copy a Python object


    mitsura@skynet. be a écrit :
    [color=blue]
    > Hi,
    >
    > I am new to Python and OO programming.
    > I need to copy a Python object (of a class I made myself).
    > new_obj = old_object doesn't seem to work since apparently new_obj is
    > then a referrence to old_obj.[/color]

    it is
    [color=blue]
    >
    > I found out that there is a module called 'copy' that allows you to do
    > a shallow or a deep copy.
    > I need a deep copy since my object contains dicts to other objects that
    > also need to be copied.[/color]

    yes but ...
    [color=blue]
    >
    > However, when I do new_object = copy.deepcopy(o ld_object) I get a
    > series of errors. The most important one:
    > "
    > TypeError: object.__new__( PySwigObject) is not safe, use
    > PySwigObject.__ new__()
    > "[/color]

    you see ?
    that illustrates there is no general solution to the deep copy problem
    [color=blue]
    >
    > So any help much appreciated.[/color]

    just provide your own copy() operator on your class
    you and only you can know how deep you want to copy things (it just
    depends on the nature of said things)
    [color=blue]
    >
    > With kind regards,
    >
    > Kris
    >
    > I am using Python 2.4[/color]

    Comment

    • mitsura@skynet.be

      #3
      Re: how to copy a Python object

      Already thanks for the reply,

      but how to write your own copy operator? Won't you always be passing
      referrences to new_obj?

      Comment

      • Schüle Daniel

        #4
        Re: how to copy a Python object

        mitsura@skynet. be wrote:[color=blue]
        > Already thanks for the reply,
        >
        > but how to write your own copy operator? Won't you always be passing
        > referrences to new_obj?[/color]

        for example this would work
        [color=blue][color=green][color=darkred]
        >>> class X(object):[/color][/color][/color]
        .... def __init__(self,l st):
        .... self.lst = lst
        .... def copy(self):
        .... return X(self.lst[:])
        .... def __str__(self):
        .... return "lst has id %i" % id(self.lst)
        ....[color=blue][color=green][color=darkred]
        >>> x=X([1,2,3])
        >>> y=x.copy()
        >>> print x[/color][/color][/color]
        lst has id 1078097132[color=blue][color=green][color=darkred]
        >>> print y[/color][/color][/color]
        lst has id 1078097228


        but I don't like that in this case self.lst must be passed
        through __init__
        I can think of another variant
        [color=blue][color=green][color=darkred]
        >>> class Y(object):[/color][/color][/color]
        .... def fill(self):
        .... self.lst = [randint(i*10,(i +1)*10) for i in xrange(5)]
        .... def __repr__(self):
        .... return "lst has id = %i" % id(self.lst)
        .... def copy(self):
        .... ret = Y()
        .... ret.lst = self.lst[:]
        .... return ret
        ....[color=blue][color=green][color=darkred]
        >>> from random import randint
        >>> y=Y()
        >>> y.fill()
        >>> y[/color][/color][/color]
        lst has id = 1078097452[color=blue][color=green][color=darkred]
        >>> print y[/color][/color][/color]
        lst has id = 1078097452[color=blue][color=green][color=darkred]
        >>> x=y.copy()
        >>> x[/color][/color][/color]
        lst has id = 1078097004

        .... anyone?
        are there better approaches?

        Regards, Daniel

        Comment

        • Juho Schultz

          #5
          Re: how to copy a Python object

          mitsura@skynet. be wrote:[color=blue]
          > Already thanks for the reply,
          >
          > but how to write your own copy operator? Won't you always be passing
          > referrences to new_obj?
          >[/color]

          If you need to modify the behaviour of copy or deepcopy, you can give
          your class __copy__ and __deepcopy__ methods. Then copy.copy and
          copy.deepcopy will use these. As a silly example, you could use:

          def __copy__(self):
          raise IOError, 'Permission denied.'


          Comment

          • Alex Martelli

            #6
            Re: how to copy a Python object

            Schüle Daniel <uval@rz.uni-karlsruhe.de> wrote:
            ...[color=blue][color=green][color=darkred]
            > >>> class X(object):[/color][/color]
            > ... def __init__(self,l st):
            > ... self.lst = lst
            > ... def copy(self):
            > ... return X(self.lst[:])
            > ... def __str__(self):
            > ... return "lst has id %i" % id(self.lst)[/color]
            ...[color=blue]
            > ... anyone?
            > are there better approaches?[/color]

            def __getstate__(se lf): return self.lst

            def __setstate__(se lf, L): self.lst = L

            and copy an instance x of X with copy.copy(x) [[after import copy, of
            course]]. This will also support pickling &c. getstate/setstate are
            generally the best approach. An equally good alternative here, omit
            setstate and just:

            def __getstate__(se lf): return dict(lst=self.l st)


            Alex

            Comment

            Working...