我知道Python是一种动态类型的语言,并且我很可能试图在这里重新创建Java行为。但是,我有一个团队在此代码库上工作,而我的代码目标是确保他们以一致的方式执行操作。让我举个例子:
class Company:
def __init__(self, j):
self.locations = []
当他们实例化Company对象时,将创建一个保存位置的空列表。现在,使用Python可以将任何内容添加到列表中。但是,我希望此列表仅包含Location对象:
class Location:
def __init__(self, j):
self.address = None
self.city = None
self.state = None
self.zip = None
我正在使用类来执行此操作,以便代码可以自我记录。换句话说,“位置仅具有这些属性”。我的目标是他们这样做:
c = Company()
l = Location()
l.city = "New York"
c.locations.append(l)
不幸的是,没有什么阻止他们简单地做c.locations.append("foo")
,也没有任何迹象表明c.locations
应该是Location对象的列表。
与开发人员团队合作时,采用Python的方式来实现一致性的方式是什么?
答案 0 :(得分:4)
OOP解决方案是确保类API的用户不必直接与您的实例属性进行交互。
一种方法是实现封装添加位置逻辑的方法。
class Company:
def __init__(self, j):
self.locations = []
def add_location(self, location):
if isinstance(location, Location):
self.locations.append(location)
else:
raise TypeError("argument 'location' should be a Location object")
您可以使用的另一个OOP概念是property。属性是为实例属性定义getter和setter的简单方法。
假设我们要为Location.zip
属性强制采用某种格式
class Location:
def __init__(self):
self._zip = None
@property
def zip(self):
return self._zip
@zip.setter
def zip(self, value):
if some_condition_on_value:
self._zip = value
else:
raise ValueError('Incorrect format')
@zip.deleter
def zip(self):
self._zip = None
请注意,属性Location()._zip
仍然可以访问和写入。下划线表示应为私有属性,nothing is really private in Python。
由于Python的自省能力强,因此没有什么是绝对安全的。您将不得不与您的团队坐下来讨论您要采用的工具和实践。
python中没有什么是真正私有的。任何类或类实例都不能 让您远离内在的一切(这使得内省 可能且功能强大)。 Python信任您。它说:“嘿,如果你想 在黑暗的地方闲逛,我会相信你有一个 有充分的理由,而且您不会遇到麻烦。”
毕竟,我们都是成年人。
--- Karl Fast
答案 1 :(得分:1)
您还可以定义一个进行安全检查的新类ListOfLocations
。像这样
class ListOfLocations(list):
def append(self,l):
if not isinstance(l, Location): raise TypeError("Location required here")
else: super().append(l)