Use instance attributes or class properties inside the class definition?

Let’s say we have this class definition…

class Student:

    def __init__(self):
        self._permission = False

    def go_to_party(self):
        if self._permission:
            print("Let's party!")
        else:
            print("I gotta study some more.")

    @property
    def permission(self):
        return self._permission

    @permission.setter
    def permission(self, parental_decision: bool):
        self._permission = parental_decision

    @property
    def is_permitted(self):
        return self._permission

Is if self._permission: ... (just like in the go_to_party() method in the class definition example) considered Pythonic or would Pythonic actually be to do if is_permitted: ... by using the class property that is defined in the class itself?

Typically, using self.permission is preferred everywhere that isn’t the permission property itself (so @property and @permission.setter would use _permission). By using self.permission (no underscore) the rest of the Student code doesn’t have to be concerned with the exact implementation of the permission attribute, just like other user code does not need to worry about it.

The TL;DR answer is:

Most Pythonic is to just use a public attribute, no properties.

But if you need to use properties, there are advantages and
disadvantages to skipping the property and using the internal private
attribute, so the answer depends on the class and your own preferences.

Most Pythonic would be to remove the getters and setters and just use a
public attribute. Python is not Java. Quote:

“In Java, you have to use getters and setters because using public
fields gives you no opportunity to go back and change your mind later to
using getters and setters. So in Java, you might as well get the chore
out of the way up front. In Python, this is silly, because you can start
with a normal attribute and change your mind at any time, without
affecting any clients of the class. So, don’t write getters and
setters.”

That was written more than 16 years ago, and it remains true. The most
Pythonic way to write your example class is:

class Student:
    def __init__(self):
        self.permission = False
    def go_to_party(self):
        if self.permission:
            print("Let's party!")
        else:
            print("I gotta study some more.")

How likely is it that permission will ever change from a single basic
flag to a more complex implementation? Not very likely. But if it does,
with properties we can cleanly change the implementation without
changing the interface, something that cannot be easily or at all done
in Java.

But don’t write that property today, because you think you might
need it in six months.

(YAGNI is not just good advice for agile or extreme programming.)

If you do decide that you need to hide the permission flag behind a
property, then inside the class, you can do anything you like
with your own class’ private attributes. If the implementation of
is_permitted is complex, then of course you will prefer to write the
code once inside the property, and always use the property. Don’t
Repeat Yourself (DRY).

But sometimes you have a complex setter, and a dirt-simple getter that
just returns the value of the private attribute:

@property
def permission(self):
    return self._permission

@permitted.setter
def permission(self, value):
    self._permission = something complicated

Of course now you should use the setter internally, DRY again. But to
just fetch the value, can you use the private field instead of the
property? Sure. That’s entirely up to you. It’s your class of course you
can use your classes private fields internally. There are advantages to
both, and the answer will probably depend on how big and complex your
class is, and whether you have subclasses or not.

Direct access to the private attribute is slightly more efficient as it
avoids the overhead of a property lookup and method call.

But it also has slightly higher internal coupling. If the getter ever
changes, you now have to change the getter and all the references to
the internal attribute. If the internal attribute ever changes, you have
to change it in many places.

@stoneleaf and @steven.daprano, thank you both for your wondeful answers! Especially, @steven.daprano, I like your extensive explanation. I highly appreciate this, guys.

Now I’ll go and improve my code. :slight_smile:

Guys, I have additional questions.

What about namings prepended with is_, like is_enabled? As I understand, those is_ namings indicate checking whether a value of an instance attribute (of bool type) – like self.enabled – is True or False. Is that correct?

Suppose a class definiton with the name Analysis has an instance attribute (of bool type) named enabled and we then create an instance analysis = Analysis(). Is it considered Pythonic to use the instance attribute analysis.enabled in an if statement as if analysis.enabled: ... or is it considered Pythonic to define a getter property named is_enabled (which checks the Boolean value of the instance attribute analysis.enabled) and then use this getter property in an if statement as if analysis.is_enabled: ...?

So, should my classes have instance attributes – like enabled, visible, focus – and then define getter properties – so like is_enabled, is_visible, has_focus – for them? Is that something that is considered Pythonic or is having only instance attributes enough and just check their Boolean value in if statements directly?

If I had difficulty choosing something, I would mimic the major or my favorite modules.
But many modules use is... as a function, and it would be more familiar to many users.

>>> sys.is_finalizing()
>>> os.path.isfile(path)
>>> inspect.isclass(obj)
>>> str.isalnum()
...

@komoto48g, so I should have an instance attribute named enabled in a class definition along with a method named is_enabled()? So like this…

class Analysis:

    def __init__(self):
        self.enabled = False

    def is_enabled(self):
        return self.enabled

So if the instance is created in some other module as analysis = Analysis(), should I change the Boolean value of the instance attribute by doing analysis.enabled = True and should I then check the Boolean value by doing analysis.is_enabled()? Is that the best standard practice in Python?

Is that the best standard practice in Python?

I would say that it is not. If you have a specific, single attribute that defines if something is enabled (enabled in this case), use that, and decide on any name that works in your case - so both enabled and is_enabled work equally well.

If there is no single attribute, but the “enableness” needs to be recalculated every time, you can either use a property as described in previous comments. A method can be used instead in two cases:

  1. You want to clearly signal that there is some logic happening there, e.g. if it will impact the performance.
  2. You want to be able to send some additional arguments to the calculation, which is not possible with a property.

The is_enabled in your example is definitely not Pythonic, as it is essentially just a getter method that duplicates the functionality of the enabled attribute.

1 Like

Hi, @PedanticHacker

No, I would say, such design is … ugly. :slight_smile:

So, the easiest and practical way is to access the self.enabled itself. Simply,

class Analysis:
    def __init__(self):
        self.enabled = False

I would do in addtion as follows (so you don’t have to worry about del obj.enabled):

class Analysis:
    enabled = False
    def __init__(self):
        self.enabled = False

I think, safe but a bit redundant way maybe

class Analysis:
    def __init__(self):
        self.__enabled = False
    
    def is_enabled(self):
        return self.__enabled
    
    def enable(self, value):
        self.__enabled = value
    
    @property
    def enabled(self):
        return self.__enabled
    
    @enabled.setter
    def enabled(self, value):
        self.__enabled = value

For example, wxPython GUI package uses both styles (but this maybe due to historical reasons and compatibility with wxWidgets)

>>> self.btn.Enabled
True
>>> self.btn.Enabled = False
>>> self.btn.IsEnabled()
False
>>> self.btn.Enable(True)
True

After all,

the answer depends on the class and your own preferences.

Thank you for the expressive answers.

I have an idea, though. What if I simply name an instance attribute as is_enabled to begin with? (Rather than having an enabled instance attribute plus an is_enabled() method.)

Would you regard the naming is_enabled as an instance attribute as peculiar?

I think no problem, but as @b11c pointed out:

is_enebaled(*args) should be a function.

@komoto48g, what if my implementation of the is_enabled() method is not to be given any arguments and not to do any calculation at all but just to simply return a value of an instance attribute? Would such an intended purpose warant the is_enabled() method to rather be defined as a class property or would an argumentless method be a better option still?

Suppose you needed is_what(*args) function in the future. There will be two styles in the library, where is_enable is a property but is_what is a function.
I don’t think many users will like it.

I was just re-reading everything in this discussion thread. Now I’m wondering why were @property, @property_name.setter, and @property_name.deleter even made available in Python if directly manipulating instance attributes is preferred and considered the best practice.

I guess Python has become bloatware over the years. Could be renamed to FatPython now if you ask me. :wink:

I know that the only way to make an attribute read-only in Python is to hide it behind a getter property and don’t provide a setter property for it. But what stops you from accessing the attribute directly? Nothing, even if the “private” attribute is prepended with 2 underscores, where this involves some simple name mangling to access it.

I really see no point for class properties to exist at all. If you can come up with just 1 example where you must (or should) use class properties where accessing instance attributes directly won’t be preferred, please let me know.

Best practice is to do this while you can. The point is that you can seamlessly switch to property when you need to add some logic to getting/setting, and the code that uses your class doesn’t need to change.

Here’s one – providing an alternate view of data:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @property
    def position(self):
        return self.x, self.y

    @position.setter
    def position(self, new_value):
        self.x, self.y = new_value
>>> pt = Point(1, 2)
>>> pt.position
(1, 2)
>>> pt.x += 10
>>> pt.position
(11, 2)

If it later turns out that it would be better if position was stored and x/y computed, the API doesn’t need to change.

@encukou, that was a good example why one would need to define class properties. :+1:

What would you say about having an enabled instance attribute of a class and then having an is_enabled object of the same class? Should this is_enabled object be defined as a method of this class or as a getter property of this class?

Please keep in mind that the sole purpose for this is_enabled object to exist is to simply return the value of the enabled instance attribute and that the definition of the is_enabled object is not going to change in the future.

That sounds unnecessary.

Thanks to each and every one of you that contributed to this discussion with helpful input. :slight_smile::+1:

Please allow me to recap my understanding acquired in this discussion thread.

I, as a software developer, trying to follow the absolute best Python practices, should always access and always modify instance attributes directly, not via getter and setter methods or via getter and setter properties.

I would only need to define getter properties (and, depending on the usage, setter properties possibly as well) in those parts of my API that might be prone to change in an undetermined time in the future to make my API easily maintainable.

But I must define getter properties (and, again, depending on the usage, setter properties possibly as well) if some calculation has to be done to the value of an instance attribute.

Furthermore, suppose that my API would need an instance attribute to be read-only, I would have to define a getter property for that instance attribute without defining a setter property for it. (That is the only way in Python to make an instance attribute read-only.)

Also, suppose that I – for some reason – decide it would be cool to have an object that checks a Boolean value of an instance attribute (with objects named as is_enabled, has_focus, etc.), the object would have to be defined as a method rather than a getter property. However, despite the strongest temptation of having such an object, I should always prefer checking the value of an instance attribute directly, not via a getter method or via a getter property. (But if the need for such an indirect getter is justified and turns out as the simplest solution to a problem, a getter method should always be used instead to a getter property because a property can’t be given arguments whereas a method can.)

Can anyone confirm that my takeaway is correct?

I wouldn’t use the word always quite so much, but yes, those are reasonable rules of thumb. Do that unless you have a reason to do something else.
The one I would not use is “a getter method should always be used instead to a getter property” : I prefer to keep things simple with an attribute or property, and if I later find the operation needs parameters, I’d add a new method with a different name. It happens, but not that often.

1 Like