关于Python中缺少const
正确性和缺少真正的private
成员,已经有很多争论(至少是这样)。我正在努力适应Python式的思维方式
假设我想要实现一个燃料箱。它有容量,可以重新加注,也可以消耗燃料。因此,我将按如下方式实施:
class FuelTank:
def __init__(self, capacity):
if capacity < 0:
raise ValueError("Negative capacity")
self._capacity = capacity
self._level = 0.0
@property
def capacity(self):
return self._capacity
@property
def level(self):
return self._level
def consume(self, amount):
if amount > self.level:
raise ValueError("amount higher than tank level")
self._level -= amount
def refill(self, amount):
if amount + self.level > self.capacity:
raise ValueError("overfilling the tank")
self._level += amount
到目前为止,我已经在代码中加入了某种程度的const
正确性:通过不实现capacity
的属性设置器,我通知客户机capacity
在构建对象后无法更改。(虽然从技术上讲,通过直接访问_capacity
始终可以做到这一点。)同样,我告诉客户机,您可以阅读level
,但请使用consume
或refill
方法来更改它
现在,我实现了一个Car
,它有一个FuelTank
:
class Car:
def __init__(self, consumption):
self._consumption = consumption
self._tank = FuelTank(60.0)
@property
def consumption(self):
return self._consumption
def run(self, kms):
required_fuel = kms * self._consumption / 100
if required_fuel > self._tank.level:
raise ValueError("Insufficient fuel to drive %f kilometers" %
kms)
self._tank.consume(required_fuel)
def refill_tank(self, amount):
self._tank.refill(amount)
我再次暗示客户端不应该直接访问_tank
。他唯一能做的事就是去做
过了一段时间,我的客户抱怨说他需要一种方法来知道油箱里还有多少燃油。因此,我决定添加第二个方法tank_level
def tank_level(self):
return self._tank.level
由于担心tank_capacity
很快就会成为必需,我开始在Car
中添加包装器方法,以访问FuelTank
的所有方法,除了consume
。这显然不是一个可扩展的解决方案。因此,我也可以将以下@property
添加到Car
@property
def tank(self):
return self._tank
但是现在客户端无法理解consume
方法不应该被调用。事实上,这种实现只比将tank
作为公共属性稍微安全一些:
def __init__(self, consumption):
self._consumption = consumption
self.tank = FuelTank(60.0)
并保存额外的代码行
总之,我有三个选择:
Car
中为FuelTank
的每个允许Car
的客户端使用的FuelTank
方法编写包装器方法(不可伸缩且难以维护)李>_tank
(名义上)私有,并允许客户端作为仅getter属性访问它。这只会保护我不受可能试图将tank
设置为完全不同对象的过分“白痴”客户端的影响。但是,否则就等于公开了tank
李>tank
,并询问客户“请不要打电话给Car.tank.consume
”我想知道在Pythonic世界中,哪一个选项被认为是最佳实践
在C++中,我将在^ {< CD34>}类中做出^ {CD7>}和^ {CD4>}方法,并声明为{{CD22>}作为^ ^ < CD10>}的私有成员,其中^ {< CD37 > }方法返回^ {< CD1>} -引用到{{CD22>}。这样,我只需要一个refill
的包装器方法,并且我允许客户机完全访问Tank
的任何const
成员(未来的维护成本为零)。就品味而言,我发现这是Python所缺乏的一个重要特性澄清。
<>我明白在C++中可以实现的几乎是不可能在Python中实现的(因为它们的根本不同)。我主要想弄清楚的是,三个备选方案中哪一个是最具python风格的?方案(2)是否比方案(3)有任何特殊优势?有没有办法使选项(1)可扩展
由于Python没有任何标准的标记方法
const
,因此不可能有内置的方法来提供限制访问它们的值(,即,一个对象)。然而,有两种习惯用法可以用来提供类似的东西,这两种习惯用法都通过Python的动态属性和反射功能变得更容易如果一个类被设计为支持这个用例,您可以拆分它的接口:只提供“real”类型的读接口,然后提供一个提供写接口并将任何未知调用转发给读卡器的包装器:
注意
Foo
并不从ReadFoo
继承;Python和C++之间的另一个区别是Python不能表达^ {CD4}},所以我们必须使用一个单独的对象。它也不能由一个来构造:客户端不能认为他们应该这样做是为了获得写访问权如果类不是为此而设计的,则可以反转包装:
这显然是更多的工作,因为您必须创建一个完整的黑名单(或白名单,尽管这样做会更难生成有用的错误消息)。但是,如果类是协作的,您可以将此方法与标记一起使用(例如,一个函数属性),以避免显式列表和两个类
相关问题 更多 >
编程相关推荐