【发布时间】:2017-09-15 03:23:23
【问题描述】:
@property 是定义 getter 的好方法。当属性是可变的时,返回的引用可用于以不受类定义控制的方式修改属性。我将使用香蕉架作为一个激励类比,但这个问题适用于任何包装容器的类。
class BananaStand:
def __init__(self):
self._money = 0
self._bananas = ['b1', 'b2']
@property
def bananas(self):
return self._bananas
def buy_bananas(self, money):
change = money
basket = []
while change >= 1 and self._bananas:
change -= 1
basket.append(self._bananas.pop())
self._money += 1
return change, basket
我希望香蕉摊位的游客为他们的香蕉付费。不幸的是,没有什么能阻止一只猴子(它不知道更好)拿走我的一根香蕉。猴子不用内部属性_banana,他们只是拿了一根香蕉不付钱。
def take_banana(banana_stand):
return banana_stand.bananas.pop()
>>> stand = BananaStand()
>>> stand.bananas
['b1', 'b2']
>>> take_banana(stand)
'b2'
>>> stand.bananas
['b1']
这个类比有点傻,但是任何具有可变属性的类都无法防止意外破坏。在我的实际情况中,我有一个具有两个必须保持相同长度的数组属性的类。使用数组,没有什么能阻止用户将第二个数组拼接到第一个数组中并默默地破坏我的等大小不变量:
>>> from array import array
>>> x = array('f', [1,2,3])
>>> x
array('f', [1.0, 2.0, 3.0])
>>> x[1:2] = array('f', [4,5,6])
>>> x
array('f', [1.0, 4.0, 5.0, 6.0, 3.0])
当数组是一个属性时,也会发生同样的行为。
我可以想到两种避免问题的方法:
- 子类数组并覆盖
__setitem__。我对此很抗拒,因为我希望能够在内部使用这种数组拼接行为。 - 更改访问器以返回数组的深层副本。返回的数组仍然是可变的,但对它的更改不会影响父对象。
有没有解决这个问题的优雅方法?我对继承属性的奇特方式特别感兴趣。
【问题讨论】:
标签: python python-3.x properties decorator python-decorators