从类内部引用属性

时间:2014-12-10 08:04:59

标签: python

假设我有一个类似

的课程
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

是否有任何替代方案具有任何速度优势,或更容易重构,或其他因素?

4 个答案:

答案 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

此处使用_passwordpassword会产生完全不同的输出。在大多数情况下,除了你想直接与它包装的对象进行交互之外,你只需要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