Frage

In the example below, I am deepcopying a base class and messing with the attributes of the copy. Why is this messing with the attributes of the original class? Is there any way to avoid this? The current code structure I am working with can't support multiple inheritance, so I really want to be able to somehow copy the class.

>>> class Base(object):
...    foo = "bar"
... 
>>> base_copy = copy.deepcopy(Base)
>>> del base_copy.foo
>>> 
>>> base_again = copy.deepcopy(Base)
>>> hasattr(base_again, 'foo')
False
>>> 
War es hilfreich?

Lösung 2

As stated in copy documentation:

This module does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types. It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged

You can try to do it using metaclasses:

class Base(object):
    foo = "bar"

# Create a new class called `base_copy` with attributes and base classes 
# from Base without inheriting from Base
base_copy = type('base_copy', Base.__bases__, dict(Base.__dict__))
# Will delete attribute on `base_copy` class
del base_copy.foo

base_again = type('base_again', Base.__bases__, dict(Base.__dict__))

print(hasattr(base_again, 'foo')) # True

You can try using deepcopy on dict(Base.__dict__) object to copy objects like list, dict and others.

Andere Tipps

copy() and deepcopy() are designed to copy objects not classes. When you pass a class the original class is returned.

Python documentation says :

This module does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types. It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.

Indeed when testing with your code we have:

In [8]: base_copy is Base
Out[8]: True

You could try messing with type() as suggested in the other answer but it's pretty hackish.

You could do

class B(A):
    pass

It's the closest I can think of that would make a copy.

Define all variables inside the constructor. You can create a new constructor which, on the basis of the argument provided, decides which all fields should exist in the object of the class.

Class Foo:
     def __init__(self):
        self.param0 = 0
        self.param1 = 0
     def __init__(self,i):
        if i == 0:
            self.param0 = 0
        if i == 1: 
            self.param1 = 1
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top