对于旨在用作不可变的类,例如:
class Immutable:
def __init__(self, field):
self._field = field
def field(self):
return self._field
没关系,可以在self
中返回__copy__
吗?
def __copy__(self):
return self
答案 0 :(得分:1)
如果您的目标是让您的班级用户可以安全地在其实例上调用copy.copy
,那么请务必随时添加__copy__
方法:
def __copy__(self):
return self
然而,这并非真的有必要。你的类的文档应该清楚它的实例是不可变的,所以任何使用你的类的人都应该知道,如果他们想在多个地方引用它,他们可以安全地重新使用一个实例,就像它们使用内置实例一样。在int
,str
,tuple
和frozenset
等不可变类型中。例如,
a, b, c = Immutable(123), Immutable(456), 42
d = {'one': a, 'two': b, 'three': c}
如果你没有提供__copy__
方法而某人 在某个实例上调用copy.copy
,那么他们将获得一个新对象,该对象是原始对象的克隆实例。如上所述定义__copy__
,他们当然只会获得对原始对象的引用。
顺便说一句,你应该将.field
(以及任何其他属性)变成property,并且不提供制定者。
class Immutable:
def __init__(self, field):
self._field = field
@property
def field(self):
return self._field
现在您可以将字段方法称为简单属性:
a = Immutable(123)
print(a.field)
当然,您仍然可以以正常方式改变._field
属性,但是任何使用您的类的人都应该知道他们不应该这样做。 :)
在问题评论中,我们讨论了在元组上调用copy.copy
会返回对原始元组的引用这一事实,即使tuple
未定义__copy__
。没有内置类型定义__copy__
,但要记住它们都是用C定义的,因此它们与Python中定义的类的工作方式略有不同。 FWIW,在任何内置的不可变类型上调用copy.copy
都会返回对原始对象的引用,并且在任何内置的可变类型上调用copy.copy
都会返回一个克隆。