下面是@property如何在重构代码时提供帮助的另一个例子(我只在下面总结):
假设你像这样创建了一个Money类:
class Money:
def __init__(self, dollars, cents):
self.dollars = dollars
self.cents = cents
用户根据这个类创建一个库,其中他/她使用例如。
money = Money(27, 12)
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 27 dollar and 12 cents.
现在让我们假设你决定改变你的Money类,去掉美元和美分属性,而是决定只跟踪美分的总数:
class Money:
def __init__(self, dollars, cents):
self.total_cents = dollars * 100 + cents
如果上面提到的用户现在尝试像以前一样运行他/她的库
money = Money(27, 12)
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
这将导致一个错误
AttributeError:“Money”对象没有属性“dollars”
这意味着现在每个依赖于你最初的Money类的人都必须更改所有使用美元和美分的代码行,这可能是非常痛苦的……那么,如何避免这种情况呢?通过使用@property!
就是这样:
class Money:
def __init__(self, dollars, cents):
self.total_cents = dollars * 100 + cents
# Getter and setter for dollars...
@property
def dollars(self):
return self.total_cents // 100
@dollars.setter
def dollars(self, new_dollars):
self.total_cents = 100 * new_dollars + self.cents
# And the getter and setter for cents.
@property
def cents(self):
return self.total_cents % 100
@cents.setter
def cents(self, new_cents):
self.total_cents = 100 * self.dollars + new_cents
当我们现在从图书馆打电话
money = Money(27, 12)
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 27 dollar and 12 cents.
它将像预期的那样工作,我们不需要更改库中的任何一行代码!事实上,我们甚至不需要知道我们所依赖的库发生了变化。
setter也可以正常工作:
money.dollars += 2
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 29 dollar and 12 cents.
money.cents += 10
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 29 dollar and 22 cents.
你也可以在抽象类中使用@property;这里我举一个最小的例子。