Python Classes | Object-Oriented Programming (OOP) Explained
이 글의 핵심
Learn Python OOP: classes, __init__, self, inheritance, encapsulation, property, magic methods, abstract classes, and polymorphism—with examples.
Introduction: What is OOP?
Object-oriented programming models programs as objects that combine state and behavior. Procedural vs OOP (sketch):
# Procedural
# 함수 정의 및 구현
def create_account(owner, balance):
return {"owner": owner, "balance": balance}
def deposit(account, amount):
account[balance] += amount
# OOP
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if amount > self.balance:
return False
self.balance -= amount
return True
Benefits: encapsulation, reuse via inheritance, clearer boundaries for change.
1. Classes and instances
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
return f"Hi, I'm {self.name}."
def is_adult(self):
return self.age >= 18
p = Person("Alice", 25)
print(p.greet())
Understanding self
class Counter:
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
return self.count
c1 = Counter()
c2 = Counter()
Class vs instance attributes
class Student:
school = "Example High"
def __init__(self, name):
self.name = name
2. Constructors and __del__
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
return self.balance
__del__ exists but rely on context managers (with) for cleanup instead of destructor semantics.
3. Inheritance and super()
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "sound"
class Dog(Animal):
def speak(self):
return f"{self.name}: woof!"
class Cat(Animal):
def speak(self):
return f"{self.name}: meow!"
print(isinstance(Dog("x"), Animal))
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
class Manager(Employee):
def __init__(self, name, salary, team_size):
super().__init__(name, salary)
self.team_size = team_size
Multiple inheritance and MRO
class Flyer:
def fly(self):
return "flying"
class Swimmer:
def swim(self):
return "swimming"
class Duck(Flyer, Swimmer):
pass
print(Duck.__mro__)
4. Encapsulation and @property
Convention: _protected, __private (name mangling to _ClassName__attr).
# 타입 정의
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.__balance = balance
def get_balance(self):
return self.__balance
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return True
return False
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value < 0:
raise ValueError("radius must be non-negative")
self._radius = value
@property
def area(self):
return 3.14159 * self._radius ** 2
5. Magic methods (dunder)
| Method | Purpose |
|---|---|
__init__ | Initialize instance |
__str__ / __repr__ | String forms |
__len__, __getitem__ | Container protocol |
__add__, __eq__ | Operators / equality |
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __repr__(self):
return f"Vector({self.x}, {self.y})"
6. @classmethod and @staticmethod
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_birth_year(cls, name, birth_year):
from datetime import date
age = date.today().year - birth_year
return cls(name, age)
class MathUtils:
@staticmethod
def is_even(n):
return n % 2 == 0
7. Abstract base classes
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Rectangle(Shape):
def __init__(self, w, h):
self.w, self.h = w, h
def area(self):
return self.w * self.h
8. Polymorphism
Same interface, different behavior—often via overridden methods or shared ABCs.
9. Practical example: library system
from datetime import datetime, timedelta
class Book:
def __init__(self, isbn, title, author, available=True):
self.isbn = isbn
self.title = title
self.author = author
self.available = available
def __str__(self):
status = "available" if self.available else "on loan"
return f"[{self.isbn}] {self.title} — {self.author} ({status})"
def __eq__(self, other):
return self.isbn == other.isbn
class Member:
def __init__(self, member_id, name):
self.member_id = member_id
self.name = name
self.borrowed_books = []
def __str__(self):
return f"Member {self.name} ({self.member_id})"
class Library:
def __init__(self):
self.books = {}
self.members = {}
self.loan_records = []
def add_book(self, book):
self.books[book.isbn] = book
print(f"Added book: {book.title}")
def register_member(self, member):
self.members[member.member_id] = member
print(f"Registered member: {member.name}")
def borrow_book(self, member_id, isbn):
if member_id not in self.members:
return "Unknown member"
if isbn not in self.books:
return "Unknown book"
book = self.books[isbn]
member = self.members[member_id]
if not book.available:
return f"'{book.title}' is already on loan"
book.available = False
member.borrowed_books.append(isbn)
due = datetime.now() + timedelta(days=14)
self.loan_records.append({
"member": member_id,
"book": isbn,
"borrow_date": datetime.now(),
"due_date": due,
})
return (
f"{member.name} borrowed '{book.title}' "
f"(due {due.strftime('%Y-%m-%d')})"
)
def return_book(self, member_id, isbn):
if isbn not in self.books:
return "Unknown book"
book = self.books[isbn]
member = self.members[member_id]
if isbn not in member.borrowed_books:
return "This book was not borrowed by this member"
book.available = True
member.borrowed_books.remove(isbn)
return f"{member.name} returned '{book.title}'"
def list_available_books(self):
return [b for b in self.books.values() if b.available]
# Example usage
library = Library()
library.add_book(Book("978-1", "Python Basics", "A. Author"))
library.register_member(Member("M001", "Dana"))
print(library.borrow_book("M001", "978-1"))
print(library.return_book("M001", "978-1"))
OOP principles (short)
- Encapsulation: hide internals; expose methods/properties.
- Inheritance: extend behavior; use
super()intentionally. - Polymorphism: program to interfaces (duck typing or ABCs).
- Abstraction: hide complexity behind simple APIs.
Common mistakes
- Forgetting
selfin__init__/ methods. - Mutable class attributes shared across instances—use instance attributes in
__init__. - Skipping
super().__init__(...)when the parent must initialize. - Assigning to a
@propertywith no setter.
Summary
- Class = blueprint; instance = concrete object.
- init initializes; self is the instance.
- Inheritance + super(); understand MRO for multiple inheritance.
- Encapsulation with naming,
__, and @property. - Dunder methods customize operators and built-ins.
@classmethod/@staticmethodfor factories and utilities.- ABC + @abstractmethod for contracts.
Next steps
Related posts
Frequently Asked Questions (FAQ)
Q. When would I use this in practice?
A. Learn Python OOP: classes, init, self, inheritance, encapsulation, property, magic methods, abstract classes, and po…
Q. What should I read before this?
A. Follow the previous article or related articles links at the bottom of each post to learn in sequence. See the Python series index for the full picture.
Q. Where can I study this more deeply?
A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.
Related Articles (Internal Links)
Other articles related to this topic.
- Python Functions | Parameters· Return Values
- Python 모듈과 패키지 | import, pip, 가상환경 완벽 정리
- C++ Inheritance & Polymorphism: virtual, Interfaces, and
- JavaScript Classes | ES6 Class Syntax Explained
Keywords Covered in This Article (Related Search Terms)
This article covers Python, Class, OOP, Inheritance, Encapsulation, Polymorphism.