🔐 Python OOP — Getter, Setter & Deleter (Using @property)

Introduction 🌟

In Python, **getter**, **setter**, and **deleter** methods are used to control how attributes are accessed, modified, and deleted. Instead of exposing attributes directly, we wrap them inside properties to ensure **validation**, **security**, and **clean code**.

Note

💡 Python uses the @property decorator to create getters,@attribute.setter for setters, and@attribute.deleter for deleters.

1. Basic Structure of Getter, Setter & Deleter 🧱

basic_getter_setter_deleter.py

class Person:
    def __init__(self, name):
        self._name = name   # protected attribute

    @property
    def name(self):         # getter
        return self._name

    @name.setter
    def name(self, value):  # setter
        self._name = value

    @name.deleter
    def name(self):         # deleter
        del self._name

p = Person("Sathish")
print(p.name)     # getter
p.name = "Arun"   # setter
del p.name        # deleter

2. Why Use Getter, Setter & Deleter? 🤔

  • ✔ To protect internal data (Encapsulation)
  • ✔ To validate data before setting
  • ✔ To run code when deleting attributes
  • ✔ To create read-only or write-only attributes
  • ✔ To avoid direct access to internal variables

3. Getter (Read-Only Attribute) 👀

getter_only.py

class Product:
    def __init__(self, price):
        self._price = price

    @property
    def price(self):
        return self._price

p = Product(500)
print(p.price)

Note

✔ No setter → attribute becomes read-only.

4. Setter (Validation Before Assignment) ✏️

setter_validation.py

class Employee:
    def __init__(self, salary):
        self._salary = salary

    @property
    def salary(self):
        return self._salary

    @salary.setter
    def salary(self, value):
        if value < 0:
            raise ValueError("Salary cannot be negative")
        self._salary = value

e = Employee(30000)
e.salary = 35000  # valid
print(e.salary)

✔ Setters add data validation & rules.

5. Deleter (Custom Delete Behavior) 🗑️

deleter_example.py

class User:
    def __init__(self, username):
        self._username = username

    @property
    def username(self):
        return self._username

    @username.deleter
    def username(self):
        print("Deleting username...")
        del self._username

u = User("admin")
del u.username

✔ Useful for cleanup, logging, and removing sensitive data.

6. Real-World Example: Temperature Control 🌡️

temperature_control.py

class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius

    @property
    def celsius(self):
        return self._celsius

    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("Temperature cannot go below absolute zero!")
        self._celsius = value

    @property
    def fahrenheit(self):
        return (self._celsius * 9/5) + 32

t = Temperature(25)
print(t.fahrenheit)
t.celsius = -300  # ❌ error

7. Real-World Example: Student Marks System 🧮

marks_example.py

class Student:
    def __init__(self, marks):
        self._marks = marks

    @property
    def marks(self):
        return self._marks

    @marks.setter
    def marks(self, value):
        if not (0 <= value <= 100):
            raise ValueError("Marks must be between 0 and 100")
        self._marks = value

s = Student(85)
s.marks = 95
print(s.marks)

8. Read-Only & Write-Only Attributes 🔒

✔ Read-Only Attribute

readonly.py

class BankAccount:
    def __init__(self, balance):
        self._balance = balance

    @property
    def balance(self):
        return self._balance   # no setter
✔ Write-Only Attribute

writeonly.py

class Secret:
    def __init__(self):
        self._password = None

    @property
    def password(self):
        raise AttributeError("Password is write-only")

    @password.setter
    def password(self, value):
        self._password = value

Note

✔ Write-only attributes are rare but useful for sensitive operations.

9. Using Getters/Setters Without Breaking Existing Code 🧠

safe_update.py

class Product:
    def __init__(self, price):
        self.price = price  # originally direct attribute

    @property
    def price(self):
        return self._price

    @price.setter
    def price(self, value):
        if value < 0:
            raise ValueError("Invalid price")
        self._price = value

p = Product(100)
print(p.price)

✔ If you change price to use validation later, existing code still works.

10. Best Practices 💡

  • ✔ Always prefix internal attributes with _
  • ✔ Use setters ONLY when validation is needed
  • ✔ Keep property methods simple and fast
  • ✔ Use deleters carefully — rarely needed
  • ✔ Use @property to make code more Pythonic and readable

Conclusion 🎉

>>“Getters, Setters, and Deleters give you full control over attribute access — combining encapsulation with the beauty of simple attribute syntax.” ✨

You now fully understand Getter, Setter & Deleter in Python! Want the next topic? Try Encapsulation, Private Attributes, Magic Methods, or Inheritance. Just tell me! 😊