How can I copy all the attributes of one Python object to another?

I have two classes from which one inherits from the other:

class DaParent(object):
    name = ''
    number = 0

class DaChild(DaParent):
    additional = ''

      

Now I create a parent element and change the attributes:

parent = DaParent()
parent.name = 'papa'
parent.number = 123

      

And from now on, I want to create a Child in which I want to copy all the attributes from the parent. I can of course do it like this:

child = DaChild()
child.name = parent.name
child.number = parent.number

      

The fact is that during development this class will have a fairly large number of attributes, and I do not constantly want to change the manual copying of attributes to the child.

Is there a way to automatically transfer the attributes of the parent to the new child? All advice is appreciated!

[EDIT] Just to explain WHY, I want to do this. I am using Peewee ORM to interact with my DB. Now I want to revise the table (this means that if the record is updated, I want to keep all previous versions). The way I am going to do this is to create a class Person

and a class PersonRevision

that inherits from the class Person

. Then I override the peewee save () method to not only save the object Person

, but copy all the attributes to the object PersonRevision

and Save that as well. Since I will never interact directly with the class PersonRevision

, I don't need shadows or any fancy stuff. I just want to copy the attributes and call the object with my method save()

.

+3


source to share


2 answers


The obvious solution is to use composition / delegation instead of inheritance:

class Parent(object):
   def __init__(self, name, number):
       self.name = name
       self.number = number


class Child(object):
    def __init__(self, parent, other):
        self.parent = parent
        self.other = other

    def __getattr__(self, name):
        try:
            return getattr(self.parent, name)
        except AttributeError, e:
            raise AttributeError("Child' object has no attribute '%s'" % name)

p = Parent("Foo", 42)
c = Child(p, "parrot")
print c.name, c.number, c.other
p.name = "Bar"
print c.name, c.number, c.other

      

This, of course, assumes that you don't really want "copies" but "links to". If you really want a copy, this is also possible, but can get tricky with mutable types:

import copy

class Parent(object):
   def __init__(self, name, number):
       self.name = name
       self.number = number


class Child(object):
    def __init__(self, parent, other):
        # only copy instance attributes from parents
        # and make a deepcopy to avoid unwanted side-effects
        for k, v in parent.__dict__.items():
            self.__dict__[k] = copy.deepcopy(v)
        self.other = other

      



If none of these solutions suit your needs, please explain your real-world use case - you might have a problem with XY.

[edit] Actually the problem is with XY. The real question is, "How to copy fields peewee.Model

to another peewee.Model

. peewee

Uses descriptors ( peewee.FieldDescriptor

) to control access to model fields and store the field names and definitions in the _meta.fields

dict model , so the simplest solution is to iterate on the original model _meta.fields

and use getattr

/ setattr

:

class RevisionMixin(object):
    @classmethod
    def copy(cls, source, **kw):
        instance = cls(**kw)
        for name in source._meta.fields:
            value = getattr(source, name)
            setattr(instance, name, value)
        return instance

class Person(peewee.Model):
     # fields defintions here


class PersonRevision(Person, RevisionMixin):
    # additional fields definitions here


p = Person(name="foo", number=42)
r = PersonRevision.copy(p, whatelse="parrot")

      

NB: untested code, never used peewee

, maybe something better to do ...

+7


source


If you have one parent with multiple children and the children need to be updated to match the parent when the parent changes, then the parent attributes will be class attributes instead, and the "copy" for the children will be automatic.

If you have multiple parents and at least some of the parents will have children, there are three options:



  • use delegation (have a child in the parent for everything it doesn't know about
  • use copy (what are you doing now)
  • use metaclasses to create a new parent class for every other parent, then every parent has its attributes as class attributes.
0


source







All Articles