Refer to a property from inside the class itself

Question:

Say I have a class that looks like

class MeasurementList:

  def __init__(self, measurement_list):
    self.__measurements = measurement_list

  @property
  def measurements(self):
    return self.__measurements

what is the most pythonic way to retrieve the value of self.measurements from inside the class; directly accessing the variable or going via the property (external accessor)? I.e.,

def do_something(self)
  # do something
  return self.measurements

or

def do_something(self)
  # do something
  return self.__measurements

Does any of the alternatives have any speed advantages, or easier refactoring, or other factors?

Asked By: Godsmith

||

Answers:

I presume you have seen code like this in Java. It is, however, deeply unpythonic to use methods where attribute access serves the purpose perfectly well. Your existing code would be much more simply written as

class MeasurementList:

   def __init__(self, measurement_list):
       self.measurements = measurement_list

Then no property is required.

The point is, presumably, to avoid allowing code external to the class to alter the value of the __measurements attribute. How necessary is this in practice?

Answered By: holdenweb

Use setters and getters both inside and outside your class. It would make your code easier to maintain once you add some additional data processing into setters and getters:

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()

From the output, you see that setter and getter are invoked:

setter
----
getter
Answered By: Konstantin

The point of properties is to add additional functionality to the process of getting/setting a field, while keeping the interface of a field.

That means you start out with a simple field, and access it as a field:

class MeasurementList:

  def __init__(self, measurement_list):
    self.measurements = measurement_list


  def foo(self):
     print("there are %d measurements" % len(self.measurements))

Then if you want/have to add additional logic to the setter/getter you convert it into a property, without having changed the interface. Thus no need to refactor accessing code.

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)

Alternative reasons for using properties are readonly properties or properties that return computed (not directly stored in fields) values. In the case of read only properties you would access the backing field directly to write (from inside the class).

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)

Keeping all that in mind you should not forget that there is no such thing as ‘private’ in python. If anyone really wants to access a private anything he can do so. It is just convention that anything starting with an underscore should be considered private and not be accessed by the caller. That is also the reason why one underscore is enough. Two underscores initiate some name mangling that is primarily used to avoid name conflicts, not prohibit access.

Answered By: PeterE

When you use properties in Python, you should almost always avoid accessing attribute under the property, unless it’s necessary. Why?

Properties in Python are used to create getter, setter and deleter, but you probably know it.
They are usually used when you process the property data during those operation. I don’t really have a good example for it right now, but consider following:

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

Here using _password and password results in quite different output. In most cases, you need simply password, both inside and outside class definition, unless you want to interact directly with object wrapped by it.

If you have the same object returned in getter and attribute, then you should follow the same practice, as you may wish sameday to add some checks or mechanics to it, and it will save you from refactoring every use of _attribute, and following that convention will also save you from errors when creating more complex descriptors.

Also, from your code, note that using __measurements (leading double underscore) results in name mangling of attribute name, so if you ever inherit from MeasurementList, you will be almost unable to access this attribute.

Answered By: Wikiii122
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.