[7일차-2] Python

송정근·2026년 5월 28일

객체지향 프로그래밍

1. 프로그래밍 방법론

프로그래밍 방법론은 프로그램을 개발하는 접근 방식이나 사고방식을 의미한다. 프로젝트 규모, 요구 사항, 개발팀의 특성에 따라 적합한 방식이 달라질 수 있다.

방법론중심 개념특징
절차적 프로그래밍순서와 절차명령을 순서대로 실행하며 함수를 이용해 작업을 분리한다.
객체지향 프로그래밍객체데이터와 기능을 객체 단위로 묶어 관리한다.
함수형 프로그래밍함수함수를 중심으로 데이터를 변환하고 부수 효과를 줄이는 데 집중한다.

1.1 절차적 프로그래밍

절차적 프로그래밍 (Procedural Programming) 은 작업을 순서대로 실행하도록 프로그램을 구성하는 방식이다. 코드 흐림이 비교적 직관적이며, 작은 츠로그램이나 순서가 중요한 작업에 적합하다.

price = 10000
quantity = 3
discount_rate = 0.1

total = price * quantity
discounted_total = total * (1 - discount_rate)

print(discounted_total)

출력 결과 :

27000.0

코드가 길어질수록 중복을 줄이기 위해 함수를 사용한다.

def calculate_total(price, quantity, discount_rate):
  	total = price * quantity
    return total * (1 - discount_rate)
  
print(calculate_total(10000, 3, 0.1))

출력 결과 :

27000.0

1.2 객체지향 프로그래밍

객체지향 프로그래밍(Object-Oriented Programming, OOP)은 데이터와 기능을 하나의 객체로 묶어 프로그램을 구성하는 방식이다.

class Order:
    def __init__(self, price, quantity):
        self.price = price
        self.quantity = quantity

    def total_price(self):
        return self.price * self.quantity


order = Order(10000, 3)
print(order.total_price())

출력 결과 :

30000

객체지향 프로그래밍은 캡슐화, 상속, 다형성 같은 개념을 활용해 코드를 재사용하고 확장하기 좋다.

1.3 함수형 프로그래밍

함수형 프로그래밍(Functional Programming) 은 함수를 중심으로 데이터를 처리하는 방식이다. 파이썬은 완전한 함수형 언어는 아니지만 map(), filter(), sorted(), 람다 함수, 컴프리헨션 등을 활용해 함수형 스타일을 작성할 수 있다.

scores = [45, 70, 88, 52, 100]

passed = list(filter(lambda score: score >= 60, scores))
print(passed)

출력 결과 :

[70, 88, 100]

2. 클래스와 객체

클래스(class) 는 객체를 만들기 위한 설계도이다. 객체가 가져야 할 데이터와 동작을 클래스 안에 정의한다.

class 클래스이름:
    클래스_속성 = 초기값

    def __init__(self, 매개변수):
        self.인스턴스_속성 = 매개변수

    def 메서드(self):
        실행할 코드

2.1 빈 클래스 만들기

클래스 내부에 아직 작성할 코드가 없다면 pass를 사용할 수 있다.

class Fruit:
    pass


apple = Fruit()
banana = Fruit()

print(apple)
print(type(apple))
print(id(apple))

print(banana)
print(type(banana))
print(id(banana))

출력 결과 :

<__main__.Fruit object at ...>
<class '__main__.Fruit'>
...
<__main__.Fruit object at ...>
<class '__main__.Fruit'>
...

apple 과 banana 는 같은 Fruit 클래스로 만들었지만 서로 다른 객체이다. 따라서 id() 값도 다르다.

2.2 객체와 인스턴스

객체(object)는 메모리에 생성된 모든 실체를 의미하는 넓은 개념이다. 파이썬에서는 숫자, 문자열, 리스트, 함수, 클래스 인스턴스가 모두 객체이다.

인스턴스(instance)는 특정 클래스에 의해 생성된 객체를 말할 때 사용하는 관계 중심의 표현이다.

class Fruit:
    pass


apple = Fruit()

print(isinstance(apple, Fruit))  # True

출력 결과 :

True

apple은 객체이면서 동시에 Fruit 클래스의 인스턴스이다.

3. 생성자와 인스턴스 변수

생성자(constructor)는 객체가 생성될 때 초기 설정을 담당하는 특별한 메서드이다. 파이썬에서는 __init__() 메서드가 생성자 역할을 한다.

3.1 __init__() 기본 구조

class Fruit:
    def __init__(self):
        print(self, "init 호출")


apple = Fruit()

출력 결과 :

<__main__.Fruit object at ...> init 호출

객체를 생성하면 __init__() 이 자동으로 호출된다. 이때 self는 생성된 인스턴스 자신을 가르킨다.

3.2 인스턴스 변수

인스턴스 변수는 각 객체마다 따로 저장되는 변수이다. 보통 __init()__ 안에서 self.변수명 형태로 만든다.

class Fruit:
    def __init__(self):
        self.name = ""
        self.quantity = 0


apple = Fruit()
banana = Fruit()

apple.name = "사과"
apple.quantity = 10

banana.name = "바나나"
banana.quantity = 5

print(apple.name, apple.quantity)    
print(banana.name, banana.quantity)  

출력 결과 :

사과 10
바나나 5

apple 의 값을 바꿔도 banana 의 값은 바뀌지 않는다. 인스턴스 변수는 객체마다 독립적으로 저장되기 때문이다.

3.3 생성자 매개변수로 초기화하기

객체를 만들 때 필요한 값을 생성자 매개변수로 전달할 수 있다.

class Fruit:
    def __init__(self, name, quantity, origin="원산지 미상"):
        self.name = name
        self.quantity = quantity
        self.origin = origin


apple = Fruit("사과", 10, "한국")
banana = Fruit("바나나", 5, "필리핀")
melon = Fruit("멜론", 3)

print(apple.name, apple.quantity, apple.origin)    
print(banana.name, banana.quantity, banana.origin) 
print(melon.name, melon.quantity, melon.origin)    

출력 결과 :

사과 10 한국
바나나 5 필리핀
멜론 3 원산지 미상

필수 매개변수를 전달하지 않으면 오류가 발생한다.

# Fruit()  # TypeError: __init__() missing required arguments

4. 메서드

메서드(method)는 클래스 내부에 정의된 함수이다. 메서드는 객체나 클래스와 관련된 동작을 수행한다.

종류첫 번째 매개변수사용 목적
인스턴스 메서드self인스턴스의 속성을 읽거나 변경한다.
클래스 메서드cls클래스 자체의 상태를 읽거나 변경한다.
정적 메서드없음클래스와 관련은 있지만 인스턴스나 클래스 상태를 직접 쓰지 않는다.

4.1 인스턴스 메서드

인스턴스 메서드는 첫 번째 매개변수로 self 를 받는다. self 를 통해 인스턴스 변수에 접근한다.

class Fruit:
    def __init__(self, name, quantity):
        self.name = name
        self.quantity = quantity

    def print_info(self):
        print(f"과일 이름: {self.name}")
        print(f"수량: {self.quantity}")

    def add_quantity(self, amount):
        self.quantity += amount
        print(f"{amount}개 추가되었다.")


apple = Fruit("사과", 10)

apple.print_info()
apple.add_quantity(5)
apple.print_info()

출력 결과 :

과일 이름: 사과
수량: 10
5개 추가되었다.
과일 이름: 사과
수량: 15

4.2 클래스 메서드와 정적 메서드

클래스 메서드는 @classmethod 데코레이터를 사용하고, 첫 번째 매개변수로 cls 를 받는다. 정적 메서드는 @staticmethod 데코레이터를 사용하며, self나 cls 를 자동으로 받지 않는다.

class Order:
    tax_rate = 0.1

    def __init__(self, price, quantity):
        self.price = price
        self.quantity = quantity

    def total_price(self):
        return self.price * self.quantity

    @classmethod
    def set_tax_rate(cls, rate):
        cls.tax_rate = rate

    @staticmethod
    def calculate_discount(price, discount_rate):
        return price * (1 - discount_rate)


order1 = Order(10000, 2)

print("총 가격:", order1.total_price())  # 20000

discounted = Order.calculate_discount(order1.total_price(), 0.2)
print("할인 적용 가격:", discounted)  # 16000.0

Order.set_tax_rate(0.2)
print("변경된 세율:", Order.tax_rate)  # 0.2

출력 결과 :

총 가격: 20000
할인 적용 가격: 16000.0
변경된 세율: 0.2

4.3 데코레이터

데코레이터(decorator) 는 기존 함수나 메서드를 직접 수정하지 않고 기능을 감싸서 추가 동작을 붙이는 문법이다.

def trace(func):
    def wrapper():
        print("함수 실행 전")
        func()
        print("함수 실행 후")

    return wrapper


@trace
def hello():
    print("hello")


hello()

출력 결과 :

함수 실행 전
hello
함수 실행 후

위 코드는 다음 코드와 같은 의미이다.

def trace(func):
    def wrapper():
        print("함수 실행 전")
        func()
        print("함수 실행 후")

    return wrapper


def hello():
    print("hello")


hello = trace(hello)
hello()

@classmethod , @staticmethod 도 데코레이터이다. 메서드가 클래스와 연결되는 방식을 바꿔준다.

5. 클래스 변수

클래스 변수는 클래스에 속하는 변수이다. 해당 클래스로 만든 모든 인스턴스가 공유하는 값이다. 객체마다 다른 값을 가져야 한다면 인스턴스 변수를 사용하고, 모든 객체가 공유해야 한다면 클래스 변수를 사용한다.

class Fruit:
    origin = "한국"

    def __init__(self, name, quantity):
        self.name = name
        self.quantity = quantity

    def print_info(self):
        print(f"원산지: {Fruit.origin}")
        print(f"이름: {self.name}")
        print(f"수량: {self.quantity}")


apple = Fruit("사과", 10)
banana = Fruit("바나나", 5)

apple.print_info()
banana.print_info()

print("----- 클래스 변수 변경 -----")
Fruit.origin = "필리핀"

apple.print_info()
banana.print_info()

출력 결과 :

원산지: 한국
이름: 사과
수량: 10
원산지: 한국
이름: 바나나
수량: 5
----- 클래스 변수 변경 -----
원산지: 필리핀
이름: 사과
수량: 10
원산지: 필리핀
이름: 바나나
수량: 5

Fruit.origin 을 변경하면 모든 인스턴스가 변경된 클래스 변수 값을 참조한다.

5.1 인스턴스 변수로 같은 이름을 만들면?

인스턴스에 클래스 변수와 같은 이름의 변수를 만들면, 그 인스턴스에서는 인스턴스 변수가 우선 조회된다.

class Fruit:
    origin = "한국"

    def __init__(self, name):
        self.name = name


apple = Fruit("사과")
banana = Fruit("바나나")

apple.origin = "미국"

print(apple.origin)   
print(banana.origin)  
print(Fruit.origin)   

출력 결과 :

미국
한국
한국

apple.origin = "미국" 은 클래스 변수 Fruit.origin을 바꾼 것이 아니라, apple 인스턴스에 origin 이라는 인스턴스 변수를 새로 만든 것이다.

10. 마무리

이번 글에서 정리한 핵심은 다음과 같다.

주제핵심
변수의 범위파이썬은 LEGB 규칙에 따라 이름을 찾는다.
클로저내부 함수가 외부 함수의 변수를 기억하는 구조이다.
함수 객체함수도 객체이므로 변수에 담고 인자로 전달할 수 있다.
콜백 함수다른 함수에 전달되어 나중에 호출되는 함수이다.
람다 함수짧은 함수를 한 줄로 표현하는 익명 함수이다.
클래스객체를 만들기 위한 설계도이다.
인스턴스 변수객체마다 따로 저장되는 값이다.
클래스 변수같은 클래스의 모든 인스턴스가 공유하는 값이다.
메서드클래스 내부에 정의된 함수로, 객체나 클래스의 동작을 표현한다.

함수는 코드를 동작 단위로 나누는 도구이고, 클래스는 데이터와 동작을 하나의 구조로 묶는 도구이다. 두 개념을 함께 이해하면 프로그램을 더 읽기 쉽고 확장 가능한 형태로 설계할 수 있다.

출처 및 참고 자료

본 정리는 강의 내용과 아래 자료를 참고하여 학습 목적으로 작성하였습니다.

https://ryuzyproject.tistory.com/288

profile
기록하며 성장하는 개발자

0개의 댓글