如题,在实际代码中,有时候会遇到一种更换类中属性的名称,比如:
class Example(object):
new_value = "foo"
def new_func(self, a, b):
return a + b
里面有两个属性,new_value和new_func,我们想换成其它名字,该怎么办。如下:
class renamed_attr(object):
"""Proxy for renamed attributes (or methods) on classes.
Getting and setting values will be redirected to the provided name,
and warnings will be issues every time.
"""
def __init__(self, new_name):
self.new_name = new_name
self._old_name = None
def old_name(self, cls):
if self._old_name is None:
for k, v in vars(cls).items():
if v is self:
self._old_name = k
break
return self._old_name
def __get__(self, instance, cls):
old_name = self.old_name(cls)
warnings.warn(
"{0}.{1} is deprecated; please use {0}.{2}.".format(
cls.__name__,
old_name,
self.new_name,
),
AttributeRenamedWarning,
stacklevel=2,
)
return getattr(instance if instance is not None else cls, self.new_name)
def __set__(self, instance, value):
old_name = self.old_name(instance.__class__)
warnings.warn(
"{0}.{1} is deprecated; please use {0}.{2}.".format(
instance.__class__.__name__,
old_name,
self.new_name,
),
AttributeRenamedWarning,
stacklevel=2,
)
setattr(instance, self.new_name, value)
继续重新定义类:
class Example(object):
new_value = "foo"
old_value = deprecation.renamed_attr("new_value")
def new_func(self, a, b):
return a + b
old_func = deprecation.renamed_attr("new_func")
obj = Example()
那么:
assertEqual(obj.old_value, "foo")
assertEqual(obj.old_func(1, 2), 3)
就这有很轻松的更换了名称,而不用修改原来的代码,只需要添加就可以了。