property 装饰器实现使用descriptor protocol,这就是我们在 Python OOP 中进行数据封装的方式。描述符是:
通常,描述符是具有“绑定”的对象属性
行为”,其属性访问已被方法覆盖
在描述符协议中。这些方法是__get__()、__set__()、
和__delete__()。如果为对象定义了这些方法中的任何一个,
据说是描述符。
通常,在其他 OOP 语言中,您使用 getter 和 setter。你会经常看到来自 Java 的人编写这样的 Python 类:
class A(object):
def __init__(self, x, y):
self._x = x
self._y = y
def getX(self):
return self._x
def getY(self):
return self._y
def setX(self, x):
self._x = x
def setY(self, y):
self._y = y
def some_method_that_uses_attributes(self):
return self.getX() + self.getY()
这很不是你在 Python 中做事的方式。 getter 和 setter 的重点是提供数据封装。我们通过将数据属性包装在 getter 和 setter 中来封装对数据属性的访问。然后,如果我们想要添加一些东西,比如说,确保 x 永远不会设置为低于 10 的值(作为一个人为的示例),我们只需更改 setX 的实现方式,我们不必修改我们的其余代码。然而,在 Python 中,我们将上面的类编写如下:
class A(object):
def __init__(self, x, y):
self.x = x
self.y = y
def some_method_that_uses_attributes(self):
return self.x + self.y
来自 Java 的人可能会惊恐地退缩:“你没有正确封装你的类!这将成为维护的噩梦!”
不,因为我们有描述符/属性:
class A(object):
def __init__(self, x, y):
self._x = x
self.y = y
@property
def x(self):
return self._x
@x.setter
def x(self, val):
if val > 10:
self._x = val
else:
raise ValueError("x must be greater than 10")
def some_method_that_uses_attributes(self):
return self.x + self.y
现在,我们不必对每个使用self.x 的方法进行折射,例如some_method_that_uses_attributes。更重要的是,当我们进行此更改时,我们类的客户端没有损坏的接口!这很好,因为它让我们避免编写一堆样板代码,并且在我们确实需要它的情况下实现描述符相对简单。此外,这使我们的代码变得漂亮漂亮,没有self.get_this() 和self.set_that(3) 贯穿整个代码,而self.this 和self.that = 3 更具可读性