一些类自带了copy()或者作用类似于浅拷贝的方法,比如内置的list、dict、decimal的Decimal等等。
copy()指的是复制一个数据相同但地址不同的对象,类似于用相同数据调用构造方法。因此在定制类的时候,如果不借助Python自带的copy库,可以在类体内调用自身的构造方法达到相同目的。
直接调用
class DateRange:
def __init__(self, start, stop):
self._start = start
self._stop = stop
if not start < stop:
raise ValueError("开始日期必须早于结束日期")
def copy(self):
return DateRange(self._start, self._stop)因为类内的方法是动态加载的,因此在Python中,方法内可以直接使用类名而不会被警告“名称未定义”。
这种办法的好处就是输入快,而且易读性很强;但缺点是如果类被继承了,且子类没有重写copy方法,会导致返回父类,而不是当前的子类。因此可以——
间接调用
class DateRange:
def __init__(self, start, stop):
self._start = start
self._stop = stop
if not start < stop:
raise ValueError("开始日期必须早于结束日期")
def copy(self):
return type(self)(self._start, self._stop) 与直接调用的唯一区别是:将DateRange()改成了type(self)()。
实际上,DateRange是一个“类”对象(而不是实例化后的那个对象),它的类型就是type,而type(self)得到的正是这个对象,故而DateRange()等价于type(self)()。
当然,其也等价于被@classmethod注解后的第一个方法参数——cls。
类方法调用
class DateRange:
def __init__(self, start, stop):
self._start = start
self._stop = stop
if not start < stop:
raise ValueError("开始日期必须早于结束日期")
@classmethod
def operate(cls, start, stop):
return cls(start, stop) 有些情况下,可能需要在类方法中调用自身的构造方法。此时,最方便也最保险的做法是直接使用cls()构造自身。因为cls本身会随着子类继承而改变,也无需再用type()转换,就能得到当前“类”对象。