Skip to main content

Creating a Class: Getter and Setter Pattern v.s. Property

Getters 

Getter and settersSetter arePattern evil.comes Evil,from evil,OOP Ilanguages say!such as C++ and Java in order to adhere to 

  • Encapsulation
    • the bundling of data/attributes and methods. 
    • restricting access to implementation details and violating state invariants  

In Python objectsit areis notconsidered Javaunpythonic. beans.Instead, Douse not@property writedecorator gettersinstead 

Class without Getter and setters.Setter 

# Basic method of setting and getting attributes in Python
# This ishas whatno Encapsulation because it directly accesses the ‘property’attributes

built-inclass isCelsius:
    for.def And__init__(self, dotemperature=0):
        notself.temperature take= thattemperature

    todef meanto_fahrenheit(self):
        thatreturn you(self.temperature should* write1.8) getters+ 32


# Create a new object
human = Celsius()

# Set the temperature
human.temperature = 37

# Get the temperature attribute
print(human.temperature)

# Get the to_fahrenheit method
print(human.to_fahrenheit())

>> 37
>> 98.60000000000001

 

Getter and setters,Setter andPattern then wrap them in ‘property’. That means that until you prove that you need anything more than a simple attribute access, don’t write getters and setters. They are a waste of CPU time, but more important, they are a waste of programmer time. Not just for the people writing the code and tests, but for the people who have to read and understand them as well.

  • Class Attributes... 
    • are variables where you can access through the instance, class, or both. 
    • holds an internal state.  
    • Two ways to access class attributes:
      1. Directly (breaks encapsulation) 
        • If accessed directly, they become part of Public API
        • Only use if sure that no behavior (methods) will ever be attached to the variables  (@dataclass?)
        • Changing implementation will be problematic:
          • Converting stored attribute -> computed attribute. Want to be able to store attributes instead of recomputing each time 
        • No internal implementation 
      2. Methods (ideal) 
        • Two methods to respect encapsulation
          • Getter: Allows Access
          • Setter: Allows Setting or Mutation 
  • Implementation
      1. Making attributes Non-public
        • use underscore in variable name ( _name ) 
      2. Writing Getter and Setter Methods for each attribute
        • In a class, __init__ is the attributes (variables)
# Making Getters and Setter methods
# PRO: Adheres to Encapsulation since get/set methods is used to change the attributes instead of direct access
# PRO: Adheres to a faux Information Hiding since converting temperature to _temperature, but no private/protected vars in Python
# CON: Has more code to change

class Celsius:
    def __init__(self, temperature=0):
        self.set_temperature(temperature)

    def to_fahrenheit(self):
        return (self.get_temperature() * 1.8) + 32

    # getter method
    def get_temperature(self):
        return self._temperature

    # setter method
    def set_temperature(self, value):
        if value < -273.15:
            raise ValueError("Temperature below -273.15 is not possible.")
        self._temperature = value


# Create a new object, set_temperature() internally called by __init__
human = Celsius(37)

# Get the temperature attribute via a getter
print(human.get_temperature())

# Get the to_fahrenheit method, get_temperature() called by the method itself
print(human.to_fahrenheit())

# new constraint implementation
human.set_temperature(-300)

# Get the to_fahreheit method
print(human.to_fahrenheit())

>> 37
>> 98.60000000000001
>> Traceback (most recent call last):
>>  File "<string>", line 30, in <module>
>>  File "<string>", line 16, in set_temperature
>> ValueError: Temperature below -273.15 is not possible.