Python Program to Demonstrate — OOP, Inheritance, and @property (Parent vs Child, Clear Rules)
Learn Python step by step.
All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules)
Jan 26, 2026
# Chapter 10 — OOP, Inheritance, and @property (Parent vs Child, Clear Rules)
This is the most “concept-heavy” chapter, so we do it in three layers:
1. Plain classes
2. Inheritance (parent → child)
3. `@property` (when and why to use it)
## 10.1 A Simple Class
```python
class Student:
def __init__(self, name):
self.name = name
def say_hi(self):
return f"Hi, I am {self.name}"
s = Student("Asha")
print(s.say_hi())
```
## 10.2 Parent vs Child (Inheritance)
### The basic idea
If you have common behavior in many classes, put it in a parent class, then specialize it in child classes.
```python
class User:
def __init__(self, name):
self.name = name
def label(self):
return f"User({self.name})"
class Student(User):
def label(self):
return f"Student({self.name})"
u = User("Rohit")
s = Student("Rohit")
print(u.label())
print(s.label())
```
### Diagram: Attribute lookup (the rule students must remember)
When you do `obj.something`, Python searches in this order:
```text
1) obj (instance) dictionary
2) obj.__class__ (its class)
3) base classes (parent, grandparent...) following MRO order
```
So if a child defines the same method name, it “wins” over the parent.
## 10.3 What “Property of Parent” vs “Property of Child” Means
In real projects, people say “this property is in parent” or “in child”.
They usually mean one of these:
- The attribute is created in the parent’s `__init__`
- The method is defined in the parent class
- A `@property` is defined in parent and reused/overridden in child
Let’s see all three cases clearly.
### Case A: Attribute created in parent `__init__`
```python
class Account:
def __init__(self, owner):
self.owner = owner
class StudentAccount(Account):
pass
a = StudentAccount("Meera")
print(a.owner)
```
Here, `owner` is created by the parent, but the child object still has it.
### Case B: Child adds its own attribute
```python
class Account:
def __init__(self, owner):
self.owner = owner
class StudentAccount(Account):
def __init__(self, owner, student_id):
super().__init__(owner)
self.student_id = student_id
a = StudentAccount("Meera", "M-101")
print(a.owner, a.student_id)
```
### Case C: Parent defines behavior, child reuses it
```python
class Account:
def label(self):
return "Account"
class StudentAccount(Account):
pass
print(StudentAccount().label())
```
## 10.4 @property (When and Why It Should Be Used)
`@property` lets you access a method like an attribute.
That sounds “small”, but it gives you big benefits:
- You keep a clean API: `user.full_name` instead of `user.get_full_name()`
- You can validate values before storing them
- You can compute values on demand
- You can keep backward compatibility (change internals without changing the public attribute)
### A clean computed property
```python
class Person:
def __init__(self, first, last):
self.first = first
self.last = last
@property
def full_name(self):
return f"{self.first} {self.last}"
p = Person("Meet", "Code")
print(p.full_name)
```
### A validated property (setter)
```python
class Product:
def __init__(self, price):
self.price = price
@property
def price(self):
return self._price
@price.setter
def price(self, value):
value = float(value)
if value < 0:
raise ValueError("price must be non-negative")
self._price = value
x = Product(10)
print(x.price)
```
### Diagram: Where property fits in lookup
```text
x.price
|
+--> finds "price" on class Product
|
+--> property object runs getter/setter code
|
+--> getter returns x._price
```
## 10.5 Parent @property vs Child @property (Most Confusing Part, Made Clear)
### Rule 1: If child defines the same property name, child wins
```python
class Base:
@property
def title(self):
return "Base Title"
class Child(Base):
@property
def title(self):
return "Child Title"
print(Child().title)
```
### Rule 2: Child can reuse parent property logic by calling `super()`
```python
class Base:
@property
def title(self):
return "Base Title"
class Child(Base):
@property
def title(self):
return super().title + " (Extended)"
print(Child().title)
```
### Rule 3: If parent has a setter, child inherits it (unless child overrides)
```python
class Base:
def __init__(self):
self._x = 0
@property
def x(self):
return self._x
@x.setter
def x(self, value):
value = int(value)
if value < 0:
raise ValueError("x must be >= 0")
self._x = value
class Child(Base):
pass
c = Child()
c.x = 5
print(c.x)
```
### When should you choose @property?
Use `@property` when:
- You want a field-like API but need logic (validation or computation)
- You want to protect internal state from invalid values
- You want to change internal storage later without breaking public code
Avoid `@property` when:
- A slow operation looks like a simple attribute (it surprises users)
- It hides side effects (example: writing to disk inside a getter)
## 10.6 `super()` in `__init__` (The “Parent Setup” Rule)
If parent builds important fields, call it.
```python
class User:
def __init__(self, name):
self.name = name
class Student(User):
def __init__(self, name, batch):
super().__init__(name)
self.batch = batch
s = Student("Riya", "2026")
print(s.name, s.batch)
```
### Diagram: Construction Flow
```text
Student.__init__ starts
-> calls User.__init__ (sets common data)
-> sets Student specific data
```
## 10.7 Inheritance vs Composition (Which One to Pick)
Use inheritance when the child truly “is a” parent.
Use composition when the object “has a” thing.
Example: a `Student` has an `Address`. Student is not an Address.
```python
class Address:
def __init__(self, city):
self.city = city
class Student:
def __init__(self, name, address):
self.name = name
self.address = address
s = Student("Aman", Address("Jaipur"))
print(s.name, s.address.city)
```
## 10.8 `@classmethod` and `@staticmethod` (Three Kinds of Methods)
### Instance method (uses `self`)
```python
class User:
def __init__(self, name):
self.name = name
def label(self):
return f"User({self.name})"
```
### Class method (uses `cls`) for alternate constructors
```python
class User:
def __init__(self, name):
self.name = name
@classmethod
def from_full_name(cls, full_name):
first = full_name.split()[0]
return cls(first)
u = User.from_full_name("Meet Code")
print(u.name)
```
### Static method (no `self`, no `cls`) for a helper that belongs here
```python
class Text:
@staticmethod
def clean(s):
return " ".join(s.split()).strip()
print(Text.clean(" meetcode python "))
```
## 10.9 Dunder Methods (Make Your Objects Feel Native)
`__str__` controls what users see, `__repr__` controls what developers see.
```python
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
p = Point(3, 4)
print(p)
```
## 10.10 A Simple “Interface” Using ABC (Pro-Level Clean Design)
You don’t need inheritance for everything, but sometimes you want a promise:
“Any child class must implement this method.”
```python
from abc import ABC, abstractmethod
class Formatter(ABC):
@abstractmethod
def format(self, text):
raise NotImplementedError()
class Upper(Formatter):
def format(self, text):
return text.upper()
print(Upper().format("meetcode"))
```
---
## Conclusion
In this article, we explored the core concepts of All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules). Understanding these fundamentals is crucial for any developer looking to master this topic.
## Frequently Asked Questions (FAQs)
**Q: What is All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules)?**
A: All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules) is a fundamental concept in this programming language/topic that allows developers to perform specific tasks efficiently.
**Q: Why is All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules) important?**
A: It helps in organizing code, improving performance, and implementing complex logic in a structured way.
**Q: How to get started with All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules)?**
A: You can start by practicing the basic syntax and examples provided in this tutorial.
**Q: Are there any prerequisites for All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules)?**
A: Basic knowledge of programming logic and syntax is recommended.
**Q: Can All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules) be used in real-world projects?**
A: Yes, it is widely used in enterprise-level applications and software development.
**Q: Where can I find more examples of All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules)?**
A: You can check our blog section for more advanced tutorials and use cases.
**Q: Is All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules) suitable for beginners?**
A: Yes, our guide is designed to be beginner-friendly with clear explanations.
**Q: How does All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules) improve code quality?**
A: By providing a standardized way to handle logic, it makes code more readable and maintainable.
**Q: What are common mistakes when using All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules)?**
A: Common mistakes include incorrect syntax usage and not following best practices, which we've covered here.
**Q: Does this tutorial cover advanced All about Python - — OOP, Inheritance, and @property (Parent vs Child, Clear Rules)?**
A: This article covers the essentials; stay tuned for our advanced series on this topic.