Python property vs method when no access to attribute is needed?

10,908

Solution 1

Properties are not intended for providing access to a private attribute. Properties are intended to give you the option of making zero-argument methods accessible as if they were attributes, so that a given "attribute" can be implemented as either a calculation or an actual attribute, without changing the interface of the class.

As such, it's usually not really a question of "better", but rather a design decision with pros and cons that depend on the context.

In this case, whatever this object is supports x.hunger, x.boredom and x.mood. Why not x.mood()? You could, although that exposes permanently in the interface that it is a calculation and is not stored.

If a prior version of the class had a "real" mood attribute, and a required invariant of the object meant that any internal method updating boredom or hunger had to also carefully set mood to be consistent, then introducing the property would be an excellent refactor; the interface stays the same, but the invariant is now guaranteed to always hold, rather than having to be carefully maintained. A whole field of bugs are made impossible to occur.

On the other hand, if mood is expensive to calculate, or has side effects, then it likely would be much better as a normal method. Making it look like an attribute access means that client code programmers will likely think of it as an attribute access, which is cheap and non-destructive; this would be a rich source of bugs or performance problems.

Solution 2

It's just a matter of taste.

A property is used where an access is rather cheap, such as just querying a "private" attribute, or a simple calculation.

A method is used where a rather "complicated" process takes place and this process is the main thing.

People are used to using getter and setter methods, but the tendency is used for useing properties more and more.

Take, as an example, the Serial class of pyserial. It has - as a heritage - methods such as getBaudRate() and setBaudRate(), but recommends to use baudrate as a reading and writing property for querying and setting the baud rate.

Solution 3

I do not think there is any real difference.

It just allows you to do obj.mood instead of obj.mood()

Solution 4

It's essentially a preference. It allows you to type object.property rather than object.property().

So when should you use which? You have to use context to decide. If the method you have returns a value based upon properties of the object, it saves you the time of creating a variable and setting it equal to some generator method (example: property = object.generateProperty(). Doesn't it make more sense to just skip this step, and make generateProperty() a property of its own?

This is the general concept as I understand it.

Share:
10,908
h3dkandi
Author by

h3dkandi

Updated on June 02, 2022

Comments

  • h3dkandi
    h3dkandi almost 2 years

    I am reading "Python programming for the absolute beginner" and in there there is this piece of code:

    @property
    def mood(self):
        unhappiness = self.hunger + self.boredom
        if unhappiness < 5:
            m = "happy"
        elif 5 <= unhappiness <= 10:
            m = "okay"
        elif 11 <= unhappiness <= 15:
            m = "frustrated"
        else:
            m = "mad"
        return m
    

    All it does is calculate on-the-fly and return the calculation. It doesn't provide access to a private attribute or any attribute of the class. Is this better as property rather than method?

  • h3dkandi
    h3dkandi about 10 years
    Yes I did get to the same conclusion that it is design decision and mood() is better as it shows calculation. This way people know that it is not stored.
  • Ben
    Ben about 10 years
    @h3dkandi Actually my conclusion (in this case) is that it is better not to expose that it's a calculation; abstract interfaces and encapsulating implementation details are the point of OO after all! But that just shows that this is a subjective decision with no "right" answer. :)
  • h3dkandi
    h3dkandi about 10 years
    Well yes I can see your point. It might be better to be hidden.
  • Tomas Silva Ebensperger
    Tomas Silva Ebensperger almost 3 years
    I agree. I would prefer the method and write the variable if the getter is expensive and you are using it a lot.
  • Valentin Fabianski
    Valentin Fabianski almost 3 years
    "cheap and non-destructive" perfect
  • h3dkandi
    h3dkandi over 2 years
    I do understand what you are trying to say but dunno if your example is good. I would implement Werewolf as a subclass of Person. The physical form dependent on the moon phase(human/wolf), as well as the mood as per your example. What I mean a werewolf is still a werewolf when in human form. I see it as a 'sick' person :). I see your example as class A and subclass B where A property is calculated and B property is 'constant'