假设我有一个类似
的课程class MeasurementList:
def __init__(self, measurement_list):
self.__measurements = measurement_list
@property
def measurements(self):
return self.__measurements
从类中检索self.measurements
的值的最pythonic方法是什么;直接访问变量或通过属性(外部访问器)?即,
def do_something(self)
# do something
return self.measurements
或
def do_something(self)
# do something
return self.__measurements
是否有任何替代方案具有任何速度优势,或更容易重构,或其他因素?
答案 0 :(得分:4)
属性的关键是在获取/设置字段的过程中添加其他功能,同时保留字段的界面。
这意味着你从一个简单的字段开始,并将其作为字段访问:
class MeasurementList:
def __init__(self, measurement_list):
self.measurements = measurement_list
def foo(self):
print("there are %d measurements" % len(self.measurements))
然后,如果您希望/必须向setter / getter添加其他逻辑,则将其转换为属性,而不更改接口。因此无需重构访问代码。
class MeasurementList:
def __init__(self, measurement_list):
self._count = 0
self.measurements = measurement_list
@property
def measurements(self):
return self._measurements
@measurements.setter
def measurements(self value):
self._measurements = value
self._count = len(value)
def foo(self):
print("there are %d measurements" % (self._count))
def bar(self):
print(self.measurements)
使用属性的其他原因是readonly属性或返回计算(不直接存储在字段中)值的属性。在只读属性的情况下,您将直接访问支持字段以进行写入(从类内部)。
class MeasurementList:
def __init__(self, measurement_list):
self._measurements = measurement_list
# readonly
@property
def measurements(self):
return self._measurements
# computed property
@property
def count(self):
return len(self.measurements)
def foo(self):
print("there are %d measurements" % (self.count))
def bar(self):
print(self.measurements)
记住这一切,你不应该忘记没有“私人”这样的事情。在python中。如果有人真的想要访问私人任何东西,他可以这样做。通常情况下,以下划线开头的任何内容都应被视为私有,并且调用者无法访问。这也是一个下划线足够的原因。两个下划线启动一些名称修改,主要用于避免名称冲突,而不是禁止访问。
答案 1 :(得分:2)
在Python中使用属性时,除非必要,否则几乎总是应该避免访问属性下的属性。为什么呢?
Python中的属性用于创建getter,setter和deleter,但您可能知道它。 它们通常在这些操作期间处理属性数据时使用。我现在还没有一个很好的例子,但请考虑以下事项:
class User:
# _password stores hash object from user's password.
@property
def password(self):
return self._password.hexdigest() # Returns hash as string
@password.setter
def password(self, val):
self._password = hash(val) # Creates hash object
此处使用_password
和password
会产生完全不同的输出。在大多数情况下,除了你想直接与它包装的对象进行交互之外,你只需要password
,在类定义的内部和外部。
如果你在getter和属性中返回了相同的对象,那么你应该遵循相同的做法,因为你可能希望在同一天添加一些检查或机制,它将使你免于重构每次使用{{1在创建更复杂的描述符时,遵循该约定还可以避免错误。
另外,从您的代码中,请注意使用_attribute
(前导双下划线)会导致属性名称的名称损坏,因此如果您从__measurements
继承,则几乎无法访问此属性。
答案 2 :(得分:1)
我认为你看过像这样的代码是Java。然而,使用属性访问完美地达到目的的方法是非常不合理的。您现有的代码将更简单地写为
class MeasurementList:
def __init__(self, measurement_list):
self.measurements = measurement_list
然后不需要任何财产。
可以说,重点是避免允许类外部的代码更改__measurements
属性的值。这在实践中有多大必要?
答案 3 :(得分:0)
在课堂内外使用设置者和获取者 。一旦你将一些额外的数据处理添加到setter和getter中,它将使你的代码更容易维护:
class C(object):
_p = 1
@property
def p(self):
print 'getter'
return self._p
@p.setter
def p(self, val):
print 'setter'
self._p = val
def any_method(self):
self.p = 5
print '----'
a = self.p
myObject = C()
myObject.any_method()
从输出中,您会看到调用了setter和getter:
setter
----
getter