클래스 메서드와 정적 메서드
2025. 3. 26. 04:10ㆍProgramming Languages/Python
클래스 메서드와 정적 메서드
1. 클래스 메서드
클래스 메서드는 클래스에 바인딩된 메서드로, @classmethod 데코레이터를 사용하여 정의합니다. 첫 번째 매개변수로 클래스 자체를 받습니다(보통 cls로 명명).
class Person:
count = 0 # 클래스 변수
def __init__(self, name, age):
self.name = name
self.age = age
Person.count += 1
@classmethod
def create_anonymous(cls, age):
# 클래스 메서드는 클래스를 첫 번째 인자로 받음
return cls("Anonymous", age)
@classmethod
def get_count(cls):
return cls.count
# 인스턴스 생성
p1 = Person("홍길동", 30)
p2 = Person("김철수", 25)
# 클래스 메서드 호출
p3 = Person.create_anonymous(40) # 익명 사용자 생성
print(p3.name, p3.age) # 출력: Anonymous 40
# 클래스 메서드로 클래스 변수 접근
print(Person.get_count()) # 출력: 3
2. 정적 메서드
정적 메서드는 인스턴스나 클래스에 바인딩되지 않는 메서드로, @staticmethod 데코레이터를 사용하여 정의합니다. 특별한 첫 번째 매개변수가 없습니다.
class MathUtils:
@staticmethod
def add(x, y):
return x + y
@staticmethod
def factorial(n):
if n <= 1:
return 1
return n * MathUtils.factorial(n - 1)
@staticmethod
def is_prime(n):
if n <= 1:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
# 정적 메서드 호출 (인스턴스 생성 없이도 사용 가능)
print(MathUtils.add(5, 3)) # 출력: 8
print(MathUtils.factorial(5)) # 출력: 120
print(MathUtils.is_prime(17)) # 출력: True
실용적인 예제: 간단한 은행 계좌 관리 시스템
아래는 지금까지 배운 객체지향 개념들을 활용한 간단한 은행 계좌 관리 시스템입니다.
from abc import ABC, abstractmethod
from datetime import datetime
# 계좌 인터페이스
class Account(ABC):
@abstractmethod
def deposit(self, amount):
pass
@abstractmethod
def withdraw(self, amount):
pass
@abstractmethod
def get_balance(self):
pass
# 거래 내역 클래스
class Transaction:
def __init__(self, amount, transaction_type, timestamp=None):
self.amount = amount
self.transaction_type = transaction_type # "deposit" 또는 "withdraw"
self.timestamp = timestamp or datetime.now()
def __str__(self):
return f"[{self.timestamp.strftime('%Y-%m-%d %H:%M:%S')}] {self.transaction_type}: {self.amount:,}원"
# 기본 계좌 클래스
class BankAccount(Account):
interest_rate = 0.02 # 기본 이자율 (클래스 변수)
def __init__(self, account_number, owner_name, balance=0):
self._account_number = account_number
self._owner_name = owner_name
self._balance = balance
self._transactions = []
@property
def account_number(self):
# 계좌번호는 마지막 4자리만 공개
hidden = '*' * (len(self._account_number) - 4)
return f"{hidden}{self._account_number[-4:]}"
@property
def owner_name(self):
return self._owner_name
def deposit(self, amount):
if amount <= 0:
raise ValueError("입금액은 0보다 커야 합니다.")
self._balance += amount
transaction = Transaction(amount, "deposit")
self._transactions.append(transaction)
return True
def withdraw(self, amount):
if amount <= 0:
raise ValueError("출금액은 0보다 커야 합니다.")
if amount > self._balance:
raise ValueError("잔액이 부족합니다.")
self._balance -= amount
transaction = Transaction(amount, "withdraw")
self._transactions.append(transaction)
return True
def get_balance(self):
return self._balance
def get_transaction_history(self):
return self._transactions
def __str__(self):
return f"계좌번호: {self.account_number}, 소유자: {self.owner_name}, 잔액: {self._balance:,}원"
@classmethod
def set_interest_rate(cls, rate):
if rate < 0:
raise ValueError("이자율은 0보다 작을 수 없습니다.")
cls.interest_rate = rate
def apply_interest(self):
interest = self._balance * self.interest_rate
self.deposit(interest)
return interest
# 당좌예금 계좌 (마이너스 통장)
class CheckingAccount(BankAccount):
def __init__(self, account_number, owner_name, balance=0, overdraft_limit=100000):
super().__init__(account_number, owner_name, balance)
self._overdraft_limit = overdraft_limit
def withdraw(self, amount):
if amount <= 0:
raise ValueError("출금액은 0보다 커야 합니다.")
# 잔액 + 마이너스 한도 이내에서 출금 가능
if amount > self._balance + self._overdraft_limit:
raise ValueError(f"출금 한도 초과. 최대 {self._balance + self._overdraft_limit:,}원까지 출금 가능합니다.")
self._balance -= amount
transaction = Transaction(amount, "withdraw")
self._transactions.append(transaction)
return True
def __str__(self):
return f"{super().__str__()}, 마이너스 한도: {self._overdraft_limit:,}원"
# 적금 계좌
class SavingsAccount(BankAccount):
interest_rate = 0.05 # 적금 계좌는 이자율이 더 높음
def __init__(self, account_number, owner_name, balance=0, term_months=12):
super().__init__(account_number, owner_name, balance)
self._term_months = term_months
self._creation_date = datetime.now()
def withdraw(self, amount):
# 만기일 이전에는 출금 불가
maturity_date = self._creation_date.replace(month=self._creation_date.month + self._term_months)
if datetime.now() < maturity_date:
months_left = (maturity_date.year - datetime.now().year) * 12 + maturity_date.month - datetime.now().month
raise ValueError(f"만기까지 {months_left}개월 남았습니다. 만기 전에는 출금할 수 없습니다.")
return super().withdraw(amount)
def __str__(self):
maturity_date = self._creation_date.replace(month=self._creation_date.month + self._term_months)
return f"{super().__str__()}, 만기일: {maturity_date.strftime('%Y-%m-%d')}"
# 은행 클래스
class Bank:
def __init__(self, name):
self.name = name
self._accounts = {}
def create_account(self, account_type, owner_name, initial_deposit=0, **kwargs):
# 계좌번호 생성
import random
account_number = str(random.randint(1000000000, 9999999999))
# 계좌 타입에 따라 다른 계좌 생성
if account_type.lower() == "checking":
overdraft_limit = kwargs.get("overdraft_limit", 100000)
account = CheckingAccount(account_number, owner_name, initial_deposit, overdraft_limit)
elif account_type.lower() == "savings":
term_months = kwargs.get("term_months", 12)
account = SavingsAccount(account_number, owner_name, initial_deposit, term_months)
else:
account = BankAccount(account_number, owner_name, initial_deposit)
self._accounts[account_number] = account
return account
def get_account(self, account_number):
return self._accounts.get(account_number)
def transfer(self, from_account_number, to_account_number, amount):
from_account = self.get_account(from_account_number)
to_account = self.get_account(to_account_number)
if not from_account or not to_account:
raise ValueError("계좌번호가 잘못되었습니다.")
# 출금 후 입금
from_account.withdraw(amount)
to_account.deposit(amount)
return True
# 사용 예제
if __name__ == "__main__":
# 은행 생성
bank = Bank("파이썬 은행")
# 계좌 생성
checking = bank.create_account("checking", "홍길동", 1000000, overdraft_limit=500000)
savings = bank.create_account("savings", "홍길동", 5000000, term_months=24)
# 계좌 정보 출력
print(checking)
print(savings)
# 거래 수행
checking.deposit(500000)
try:
checking.withdraw(2000000) # 잔액 초과지만 마이너스 한도 내
except ValueError as e:
print(f"오류: {e}")
try:
savings.withdraw(1000000) # 만기 전 출금 시도
except ValueError as e:
print(f"오류: {e}")
# 계좌 이체
try:
bank.transfer(checking._account_number, savings._account_number, 300000)
except ValueError as e:
print(f"오류: {e}")
# 거래 내역 확인
print("\n거래 내역:")
for transaction in checking.get_transaction_history():
print(transaction)
# 이자 적용
interest = checking.apply_interest()
print(f"\n적용된 이자: {interest:,}원")
print(f"이자 적용 후 잔액: {checking.get_balance():,}원")
'Programming Languages > Python' 카테고리의 다른 글
| 연결 리스트(Linked List) (0) | 2025.03.27 |
|---|---|
| 특수 메서드 (매직 메서드) (0) | 2025.03.26 |
| 추상 클래스와 인터페이스 (0) | 2025.03.26 |
| 다형성 (Polymorphism) (0) | 2025.03.26 |
| 캡슐화(Encapsulation) (0) | 2025.03.26 |