0

Here are two examples of classes that handle their attribute differently.

class MyClassA():
    def __init__(self):
        self.my_attribute = 1

class MyClassB():
    def __init__(self):
        self._my_attribute = 1

    def get_my_attribute(self):
        return self._my_attribute

    def set_my_attribute(self, value):
        self._my_attribute = value

Is there a python consensus on which is best practice?

DJames
  • 571
  • 3
  • 17
  • 1
    To whoever voted to close as opinion-based - I don't think that's the case. There's a clear best practice here, namely to pick the solution that meets the requirements. The language has well-defined instruments for both scenarios, free of opinion. – Grismar Jul 04 '23 at 13:45
  • 1
    And indeed PEP8 says *"For simple public data attributes, it is best to expose just the attribute name, without complicated accessor/mutator methods."* https://peps.python.org/pep-0008/#designing-for-inheritance – slothrop Jul 04 '23 at 13:53

2 Answers2

1

Best practice is to pick the one that meets your needs. If you need someone using your class to use the getter and setter - for example to perform checks, or to take care of required side-effects - then that's what you should do.

If it's just an attribute that you're happy to have changed by other code (no side-effects) the first solution is fine.

Note that there's also @property decorators for a nicer way to do the second type - which would be best practice over these get_... and set_... methods:

class MyClassB():
    def __init__(self):
        self._my_attribute = 1

    @property
    def my_attribute(self):
        return self._my_attribute

    @my_attribute.setter
    def my_attribute(self, value):
        self._my_attribute = value

Note that adding the _ doesn't actually hide the attribute, it just generates warnings in editors that respect it:

b = MyClassB()
print(b.my_attribute)
b.my_attribute = 10
print(b.my_attribute)
print(b._my_attribute)  # generates a warning, but works all the same

Output:

1
10
10
Grismar
  • 27,561
  • 4
  • 31
  • 54
1

In python, the best practice is to use properties. Properties "look" like attributes so they are easy to use and understand from the clients prospective but they have all the flexibility and control of methods. For example, you can have a property of a rectangle class called area that computes the area of the rectangle.

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    @property
    def area(self):
         return self.width * self.height

>>> my_rect = Rectangle(10, 20)
>>> my_rect.area
200
>>> my_rect.width = 5
>>> my_rect.area
100
rene
  • 146
  • 5
  • 2
    Right, but in OP's example the getter and setter are trivial - they don't apply any logic, just store and retrieve the value. So as PEP8 says, it's appropriate to *"expose just the attribute name, without complicated accessor/mutator methods."* https://peps.python.org/pep-0008/#designing-for-inheritance One thing that's good about properties is that when a class uses a basic attribute, it's easy to go back and replace it with a property if and when it's necessary. – slothrop Jul 04 '23 at 14:18