Копировать конструктор в python?
есть ли конструктор копирования в python ? Если нет, то что бы я сделал, чтобы добиться чего-то подобного ?
ситуация такова, что я использую библиотеку, и я расширил один из классов там с дополнительной функциональностью, и я хочу иметь возможность конвертировать объекты, которые я получаю из библиотеки в экземпляры моего собственного класса.
6 ответов:
Я думаю, что вы хотите модуль копирования
import copy x = copy.copy(y) # make a shallow copy of y x = copy.deepcopy(y) # make a deep copy of y
вы можете управлять копированием почти так же, как вы управляете огурец.
в python конструктор копирования может быть определен с помощью аргументов по умолчанию. Допустим, вы хотите, чтобы обычный конструктор запускал функцию
non_copy_constructor(self)
и конструктор копирования должен работатьcopy_constructor(self, orig)
. Тогда вы можете сделать следующее:class Foo: def __init__(self, orig=None): if orig is None: self.non_copy_constructor() else: self.copy_constructor(orig) def non_copy_constructor(self): # do the non-copy constructor stuff def copy_constructor(self, orig): # do the copy constructor a=Foo() # this will call the non-copy constructor b=Foo(a) # this will call the copy constructor
для вашей ситуации я бы предложил написать метод класса (или это может быть статический метод или отдельная функция), который принимает в качестве аргумента экземпляр класса библиотеки и возвращает экземпляр вашего класса со всеми применимыми атрибутами, скопированными.
простой пример моей обычной реализации конструктора копирования:
import copy class Foo: def __init__(self, data): self._data = data @classmethod def from_foo(cls, class_instance): data = copy.deepcopy(class_instance._data) # if deepcopy is necessary return cls(data)
здание на @Godsmith это мысли и решение нужно @Zitrax (я думаю) делать копирование данных для всех атрибутов в конструкторе:
class ConfusionMatrix(pd.DataFrame): def __init__(self, df, *args, **kwargs): try: # Check if `df` looks like a `ConfusionMatrix` # Could check `isinstance(df, ConfusionMatrix)` # But might miss some "ConfusionMatrix-elligible" `DataFrame`s assert((df.columns == df.index).all()) assert(df.values.dtype == int) self.construct_copy(df, *args, **kwargs) return except (AssertionError, AttributeError, ValueError): pass # df is just data, so continue with normal constructor here ... def construct_copy(self, other, *args, **kwargs): # construct a parent DataFrame instance parent_type = super(ConfusionMatrix, self) parent_type.__init__(other) for k, v in other.__dict__.iteritems(): if hasattr(parent_type, k) and hasattr(self, k) and getattr(parent_type, k) == getattr(self, k): continue setattr(self, k, deepcopy(v))
этой
ConfusionMatrix
класс наследует apandas.DataFrame
и добавляет кучу других атрибутов и методов, которые должны быть пересчитаны, еслиother
данные матрицы можно скопировать сверх. Поиск решения - это то, как я нашел этот вопрос.
у меня аналогичная ситуация, отличающаяся тем, что новому классу нужно только скопировать атрибуты. Таким образом, используя идею @Dunham и добавляя некоторую специфику к предложению @meisterluk, метод @meisterluk "copy_constructor" может быть:
from copy import deepcopy class Foo(object): def __init__(self, myOne=1, other=None): self.two = 2 if other <> None: assert isinstance(other, Foo), "can only copy instances of Foo" self.__dict__ = deepcopy(other.__dict__) self.one = myOne def __repr__(self): out = '' for k,v in self.__dict__.items(): out += '{:>4s}: {}, {}\n'.format(k,v.__class__,v) return out def bar(self): pass foo1 = Foo() foo2 = Foo('one', foo1) print '\nfoo1\n',foo1 print '\nfoo2\n',foo2
вывод:
foo1 two: <type 'int'>, 2 one: <type 'int'>, 1 foo2 two: <type 'int'>, 2 one: <type 'str'>, one