无法从有关此主题的其他线程中得到直接答案:
在 Python 中,使用之间的主要区别是什么
class Foo(object):
def __init__(self, x):
self.x = x
Run Code Online (Sandbox Code Playgroud)
和
class Foo(object):
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
Run Code Online (Sandbox Code Playgroud)
从外观上看,以这种方式使用@property 会使 x 只读……但也许有人有更好的答案?谢谢/弗雷德
装饰property器实现使用描述符协议,这就是我们在Python OOP中进行数据封装的方式。描述符是:
\n\n一般来说,描述符是一种具有\xe2\x80\x9c绑定\n行为\xe2\x80\x9d的对象属性,其属性访问已被描述符协议中的方法覆盖\。这些方法是
\n__get__(),__set__(),\n 和__delete__()。如果为对象定义了任何这些方法,则称其为描述符。
通常,在其他 OOP 语言中,您使用 getter 和 setter。你会经常看到来自 Java 的人编写如下的 Python 类:
\nclass A(object):\n def __init__(self, x, y):\n self._x = x\n self._y = y\n def getX(self):\n return self._x\n def getY(self):\n return self._y\n def setX(self, x):\n self._x = x\n def setY(self, y):\n self._y = y\n def some_method_that_uses_attributes(self):\n return self.getX() + self.getY()\nRun Code Online (Sandbox Code Playgroud)\n这与您在 Python 中做事的方式非常不同。getter 和 setter 的目的是提供数据封装。我们通过将数据属性包装在 getter 和 setter 中来封装对数据属性的访问。然后,如果我们想添加一些东西,比如说,确保x永远不会设置为低于 10 的值(作为一个人为的示例),我们只需更改方式setX实现方式,而不必修改其余部分代码。然而,在 Python 中,我们将上面的类编写如下:
class A(object):\n def __init__(self, x, y):\n self.x = x\n self.y = y\n def some_method_that_uses_attributes(self):\n return self.x + self.y\nRun Code Online (Sandbox Code Playgroud)\n来自 Java 的人可能会惊恐地退缩:“你没有正确封装你的类!这将成为维护的噩梦!”
\n不,因为我们有描述符/属性:
\nclass A(object):\n def __init__(self, x, y):\n self._x = x\n self.y = y\n @property\n def x(self):\n return self._x\n @x.setter\n def x(self, val):\n if val > 10:\n self._x = val\n else:\n raise ValueError("x must be greater than 10")\n def some_method_that_uses_attributes(self):\n return self.x + self.y\nRun Code Online (Sandbox Code Playgroud)\n现在,我们不必折射每个使用 的方法self.x,例如some_method_that_uses_attributes。更重要的是,当我们进行此更改时,我们班级的客户端不会出现损坏的界面!这很好,因为它让我们避免编写一堆样板代码,并且在我们确实需要它的情况下实现描述符相对简单。而且,这使得我们的代码变得漂亮和漂亮,没有self.get_this()和self.set_that(3)所有的代码一样,并且更具可读性self.this和self.that = 3
对于您的示例,是的,这允许您拥有只读属性。此外,属性可以让您看起来拥有比实际更多的属性。考虑一个带有.radius和的圆.area。可以根据半径计算面积,而不必同时存储
import math
class Circle(object):
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return math.pi * (self.radius ** 2)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2091 次 |
| 最近记录: |