无法从这个问题的其他主题得到直接答案:
在Python中,使用
之间的主要区别是什么class Foo(object):
def __init__(self, x):
self.x = x
和
class Foo(object):
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
通过这种方式使用@property看起来让x只读...但也许有人有更好的答案?谢谢/弗雷德
答案 0 :(得分:4)
对于您的示例,是的,这允许您具有只读属性。此外,属性可以让您看起来拥有比实际更多的属性。考虑使用.radius
和.area
的圈子。该区域可以根据半径计算,而不必同时存储
import math
class Circle(object):
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return math.pi * (self.radius ** 2)
答案 1 :(得分:4)
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
来自爪哇的人可能会惊恐地退缩:“你没有正确地封装你的课程!这将成为维护的噩梦!”
不,因为我们有描述符/属性:
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
答案 2 :(得分:-1)
查看关于Python属性的这篇SO帖子 - 它具体指的是getter / setter,但答案分解了很多关于它们的内容,我相信你想知道的一切都在那里:Python @property versus getters and setters