Вызов метода при копировании объекта

#python #python-3.x #class #oop

#питон #python-3.x #класс #ооп

Вопрос:

У меня есть следующий класс:

 class MyClass:

    def __init__(self, value1, value2):
        self.value1 = value1
        self.value2 = value2

    def normalize(self):
        self.value1 = 1
        return self
 

Цель normalize метода состоит в том, чтобы гарантировать, что всякий раз, когда копируется «старый» экземпляр MyClass , атрибут value1 устанавливается обратно 1 .

Например:

 myclassA = MyClass(15,25)
myclassB = myclassA.normalize()
print(myclassB.value1)
print(myclassB.value2)
>>1
>>25
 

Это работает. Однако есть ли способ добиться того же результата без отдельного метода ( normalize() в моем случае)? Могу ли я сделать так, чтобы это происходило автоматически всякий раз, когда экземпляр создается как копия из другого экземпляра MyClass класса?

Комментарии:

1. Почему вы хотите скопировать существующий экземпляр? Почему бы не создать новый?

2. На самом деле вы не делаете здесь «копию», вы же знаете об этом, верно?

3. На самом деле вы не сделали никаких копий. myclassA и myclassB оба ссылаются на один и тот же объект, и если вы проверите myclassA.value1 , то увидите значение 1 . Python не похож на C , где неявные копии происходят повсюду. В частности, присваивание, передача аргументов и возвращаемые значения работают без создания копий. См. nedbatchelder.com/text/names.html

4. Как создаются копии? Вы имеете в виду с copy.copy помощью? В Python нет понятия «создание копии».

Ответ №1:

Лучше сделать это с помощью __copy__ :

 class MyClass:

    def __init__(self, value1, value2):
        self.value1 = value1
        self.value2 = value2

    def __copy__(self):
        return self.__class__(1, self.value2) 
 

затем:

 In [5]: from copy import copy                                                                                                                                                                  

In [6]: myclassA = MyClass(15,25) 

In [7]: myclassB = copy(myclassA)   

In [15]: myclassA.value1                                                                              
Out[15]: 15

In [16]: myclassB.value1                                                                                        
Out[16]: 1

In [17]: myclassA.value2                                                                                        
Out[17]: 25

In [18]: myclassB.value2                                                                                        
Out[18]: 25