OOP1
절차 지향 프로그래밍 Procedural Programming
프로그램을 ‘데이터
’와 ‘절차
’로 구성하는 방식의 프로그래밍 패러다임
순서 중시
특징
데이터
와 해당 데이터를 처리하는함수(절차)
가 분리되어 있으며, 함수 호출의 흐름이 중요- 코드의 순차적인 흐름이 함수 중심
함수 호출의 순서가 중요한 패러다임이다.
함수랑 데이터는 별도로 분리되어있다.
⇒ 프로그램의 전체적 흐름을 함수가 이끈다
- 데이터를 다시 재사용하는 것 보다는 처음부터 끝까지 실행되는 결과물을 중시
단점 : 소프트웨어 위기(Software Crisis)
하드웨어의 발전⇒ 컴퓨터 계산 용량과 문제의 복잡성이 급격히 증가 ⇒ 소프트웨어가 따라가지 못해서 생긴 충격

function3 에 문제가 생기면 function3을 활용해야만 하는 프로그램들이 고장난다. (= 절차 중간에 문제가 생겼을 때 소프트웨어가 무너지는 현상이 발생)
⇒ 새로운 패러다임의 필요
⇒ 객체 지향 프로그래밍 등장
데이터는 함수의 재료로서 쓰이는 식 이었다.
객체 지향 프로그래밍 Object Oriented Programming(OOP)
데이터와 해당 데이터를 조작하는 메서드를 하나의 객체
로 묶어 관리하는 방식의 프로그래밍 패러다임
데이터와 함수를 같이 묶어서 생각한다. ⇒ 관점이 변했다.
전사 마법사 예

절차 : 공격을 한다(전사가) ↔ 객체: 전사가 베기를 한다, 마법사가 회북을 한다.
캐릭터(부모) 와 전사,마법사(자식) 간의 상하관계가 보인다.(클래스가 중심이 된다.)
↔ 절차 지향에서는 공격,수비(함수들)이 중요했다.
절차 지향 vs 객체 지향
절차지향
- 데이터와 해당 데이터를 처리하는 함수(절차)가 분리
- 함수 호출의 흐름이 중요
객체 지향
- 데이터와 해당 데이터를 처리하는 메서드(메시지)를 하나의 객체(클래스)로 묶음
- 객체 간 상호작용과 메시지 전달이 중요
객체지향은 비교적 순서를 중요하게 생각하지 않는다.
클래스 Class 붕어틀
파이썬에서 타입
을 표현하는 방법
- 객체를 생성하기 위한 설계도, 하지만 Class도 객체다
데이터
(변수)와기능
(함수, 메소드)을 함께 묶는 방법을 제공print(type(x)
) ⇒<'class' ‘str’>
- 가수(클래스)로 특정 가수들(객체)를 찍어낸다. ⇒ blue print (청사진) 처럼 쓰인다.
객체 object 붕어빵
클래스에서 정의한 것을 토대로 실제로 메모리에 할당된 것
⇒ 파이썬의 모든 것은 객체 (변수, 함수, 클래스 무엇이든 넓은 개념)
속성(정보)(변수)과 행동(동작)(메서드)으로 구성된 모든 것
붕어 틀을 먹을 순 없으니 붕어빵을 먹어야 한다.
클래스와 객체
인스턴스 : 클래스로 만든 객체
⇒ 많은 객체들이 있지만 클래스를 통해서 만든 객체를 특별히 인스턴스라고 불러준다.
- 클래스를 만든다 ==
타입
을 만든다 - 클래스 안에 변수와 메서드
- 변수 name의 타입은 str class
⇒변수 name은 str 클래스의 인스턴스이다.
⇒ 결국 문자열 타입의 변수는 str 클래스로 만든
인스턴스
다.
⇒ 우리가 사용해왔던 데이터 타입은 사실 모두 클래스였다.
name = 'Alice'
print(type(name)) #
print(help(str)) # class str(object)~~~
문자열 타입( Class )의 객체( instance )
‘’, ’hello. ’파이썬’
리스트 타입(Class )의 객체 (instance )
[1,2,3], [1], [], ['hi']
class str
라는 거대한 객체 안에 .upper
라는 함수가 존재함 ⇒ 메서드로 사용 가능
흐름
’hello’.upper()
문자열.대문자로( ) ⇒ 객체.행동( ) ⇒ 인스턴스.메서드( )
[1,2,3].sort()
리스트.정렬해() ⇒ 객체.행동() ⇒ 인스턴스.메서드()
⇒ 메서드도 함수지만 함수(변수)
가 아닌 인스턴스.메서드()
로 쓰는 이유
하나의 객체(object)는 특정 타입
의 인스턴스(instance)이다.
- 문자열 데이터들은 모두 string클래스의 인스턴스
- 리스트 데이터들은 모두 list클래스의 인스턴스
객체의 특징
타입: 어떤 연산자(poerator) 와 조작(method)이 가능한가?
속성(attribute): 어떤 상태(데이터)를가지는가?
조작법(method): 어떤 행위(함수)를 할 수 있는가?
⇒ 객체 = 속성 + 기능(Method)
클래스 (다시 알아보기)
데이터와 기능을 함꼐 묶는 방법을 제공
# 클래스 정의
class Person: # 왜 대문자일까? PascalCase 표기법 차이
pass # snake_case도 가능 but 사회적 합의로 인해 표기법을 다르게 함 # 클래스 정의할 때 () 생략 가능
# 인스턴스 생성
iu = Person() # 원래는 변수겠지만, OOP 의 관점에서 인스턴스라고 한다.
# '인스턴스 변수 = 생성자 함수' 형태
# 메서드 호출
iu.메서드()
# 속성(변수) 접근
iu.attribute
Class는 병사를 생성하고 메서드와 속성을 제공해주고, 병사는 메서드와 속성을 자기가 활용한다.
클래스 기본 활용
class Person: # 속성 blood_color = 'red' #클래스 변수 def __init__(self, name): # 이건 인스턴스가 못씀, name은 인스터스가 가지는 변수 self.name = name #인스턴스 변수, 우항 name은 파라미터 pass # 메서드 def singing(self): return f'{self.name}가 노래합니다.'
# 인스턴스 생성
singer1 = Person('iu') # 클래스(인자)
singer2 = Person('BTS')
# 메서드를 호출
print(singer1.singing()) #iu가 노래합니다.
print(singer2.singing()) #BTS가 노래합니다.
# 설계도는 다른데, 결과는 다르다.
print(singer1.blood_color) # red
print(singer2.blood_color) # red
생성자 함수 def __init__(self, name):
객체를 생성할 때 자동으로 호출하는 특별한 메서드
매직 메서드의 한 종류(__함수이름__)
객체의 초기화를 담당, 초기 값이 필요하다고 하면 쓰임
기본생성자: 파라미터가 없다. Person()
으로만 쓰는것
인스턴스 변수 self.name = name
인스턴스(객체)마다 별도로 유지되는 변수
인스턴스마다 독립적인 값 가짐, 인스턴스가 생성 될 때마다 초기화됨
인스턴스들이 같은 공간을 공유하지 않음
클래스 변수 blood_color = 'red'
모든 인스턴스들이 공유(참조)하는 변수, 참조
가 가지는 특징 가진다
인스턴스 메서드 def singing(self):
인스턴스가 쓰는 메서드니까 인스턴스 메서드
클래스는 이 메서드를 관리
만 할 뿐 쓰는 것은 인스턴스니까
각각의 인스턴스 변수에 접근하고 수정하는 등의 작업을 수행
인스턴스와 클래스 간의 이름 공간 (namespace)
클래스 정의 ⇒ 클래스 & 해당하는 namespace 생성
인스턴스를 만들면, 인스턴스 객체가 생성되고 독립적인
namespace 생성
⇒ 인스턴스를 만들 떄 마다 전혀 다른 공간을 부여받는다.
어떠한 인스턴스가 인스턴스.ssafy
라는 속성값을 접근하려 하면 일단 본인한테 있는지 확인 ⇒ Class가 가지고 있는지 찾아 올라간다.
독립적인 이름공간이 가지는 이점
- 각 인스턴스는 독립적인 메모리 공간 가짐
⇒ 클래스와 다른 인스턴스 간에는 서로의 데이터나 상태에 직접적인 접근이 불가능
- 객체 지향 프로그래밍의 중요한 특성 중 하나로,
클래스와 인스턴스를
모듈화
하고 각각의 객체가 독립적으로 동작하도록 보장 - 이를 통해 클래스와 인스턴스는 다른 객체들과의 상호작용에서 서로 충돌이나 영향을 주지 않으면서 독립적으로 동작 가능
⇒ 코드의 가독성, 유지보수성, 재사용성을 높이는데 도움을 줌
가장 큰 절차지향과 객체지향의 가장 궁극적인 차이점 하나
순서를 가진다 ⇒ 서로 복잡하게 영향을 준다 . 2번은 3번에 반드시 영향을 준다.
클래스 변수 활용
가수가 몇 명인지 확인하고 싶다면?
인스턴스가 생성 될 때마다 __init__
실행됨 ⇒ 이를 이용해서 정수 형태의 클래스 변수가 늘어나도록 설정할 수 있음
클래스 변수와 인스턴스 변수
클래스 변수를 변경할 때는 항상 클래스.클래스변수
형식으로 변경
self
가 붙는다 = self 변수
LEGB 처럼 움직인다. (local → enclosed → global → built-in)
c2.pi = 5
: c2의 인스턴스 변수 pi에 값을 할당 =⇒ Class 변수와 상관 없다
메서드 종류 (용도를 나눠둔것)
- 인스턴스 메서드
- 클래스 메서드
- 정적 메서드
인스턴스 메서드 instance
클래스로부터 생성된 각 인스턴스에서 호출할 수 있는 메서드
⇒ 인스턴스의 상태를 조작하거나 동작을 수행
인스턴스 메서드는 클래스를 조작하진 않음
인스턴스 메서드 구조
반드시 첫 번째 매개변수로 인스턴스 자기 자신(self)을 전달 받음
클래스 내부에 정의되는 메서드의 기본
class MyClass:
def instance_method(self, arg1, ...): # 문법상 'self' 가 아닌 다른 이름도 괜찮음 but 암묵적인 합의로 self를 쓰자
pass
self 동작 원리
- upper 메서드를 사용
‘hello’.upper()
- 하지만 실제 파이썬 내부 동작
str.upper('hello')
- str 클래스가 upper 메서드를 호출 ⇒ 첫 번째 인자로 문자열 인스턴스(
’hello’
)가 들어감
⇒ 인스턴스 메서드의 첫번째 매개변수가 반드시 인스턴스 자기 자신인 이유
‘hello’.upper()
은str.upper('hello')
를 객체 지향 방식의 메서드로 호출하는 표현(단축형 호출)- ‘hello’ 라는 문자열 객체가 단순히 어딘가의 함수로 들어가는 인자가 아닌 객체 스스로 메서드를 호출하여 코드를 동작하는 객체 지향적 표현
생성자 메서드 constructor
인스턴스 객체가 생성될 때 자동으로 호출되는 메서드
⇒ 인스턴스 변수들의 초기값을 설정 def __init__(self):
구조
class Person:
def __init__(self):
print('인스턴스 생성')
# 인스턴스가 만들어지면 __init__이 바로 실행됨
person1 = Person() # 인스턴스 생성
클래스 메서드 clas
클래스가 호출하는 메서드
⇒ 클래스 변수를 조작 or 클래스 level의 동작을 수행
클래스 메서드 구조
@classmethod
데코레이터를 사용하여 정의, 없으면 인스턴스 메서드다.꾸며주는 함수그냥 업그레이드 해주는 느낌으로 기억하고 있으면 됨
- 호출 시, 첫번째 인자로 호출하는 클래스(
cls
)가 전달됨cls
도 단순한 매개변수 이름, 바꿔도 됨 But 암묵적인 합의에 의해 금지함⇒ 상속을 위해
MyClass.count
가 아닌cls.count
를 쓴다.
class MyClass:
count = 0
@classmethod
def class_method(cls, arg1, ...) #cls 를 self로 써도 문제는 발생 X print(cls.count)
pass
스테틱(정적) 메서드 static
클래스와 인스턴스와 상관없이 독립적으로 동작하는 메서드
⇒ 주로 클래스와 관련, but 인스턴스와 상호작용이 필요X 할 때 사용
일반함수처럼 쓰는 함수들
구조
@staticmethod
데코레이터를 사용하여 정의
호출 시 필수적으로 작성해야 할 매개변수 X
즉, 객체 상태나 클래스 상태를 수정X == 단지 기능(행동)만을 위한 메서드로 사용
클래스.스태틱메소드
식으로 사용
각자의 역할
Class가 사용해야 할 것
- 클래스 Method
- 스태틱 Method
- 인스턴스 Method(호출은 가능, 권장 X)
인스턴스가 사용해야 할 것
- 인스턴스 Method
- 클래스, 스태틱 Method {호출은 가능함(거슬러 올라갈 수 있어서) but 권장 X}
- 클래스는 모든 메서드를 호출 할 수 있음
But 클래스는 클래스 메서드와 스태틱 메서드만 사용하도록 한다.
- 인스턴스도 모든 메서드를 호출 할 수 있음
But 인스턴스는 인스턴스 메서드만 쓰도록 하자
⇒ 할수있다 ≠ 써도 된다.
각각의 메서드는 OOP 패러다임에 따라 명확한 목적에 따라 설계된 것이기 때문에 클래스와 인스턴스 각각 올바른 메서드만 사용하도록 해야 한다.
파이썬은 규칙이 강하진 않다 ⇒ 자유성은 높음, 하지만 실수가 많아 질 수 있다.
매직 메서드
- 범주를 따지면 인스턴스 메서드에 속함
- 특정 상황에 자동으로 호출되는 메서드 ⇒ 직접활용할 일은 잘 없다
- Double underscore(__) 가 있는 메서드는 특수한 동작을 위해 만들어진 메서드
- 스페셜 or 매직 메서드라고 불림
- 첫 매개변수는 무조건
self
예시
__-str__(self), __len__(self)
__lt__(self,other), le, eq, gt, ge, ne
데코레이터 Decorator
다른 함수의 코드를 유지한 채로 수정하거나 확장하기 위해 사용되는 함수
인자로 함수를 받아서 쓴다 → 원본 함수를 꾸며서 사용할 때 쓰는 편
def my_decorator(func): #my_function이 여기 매개함수로 들어감 def wrapper(): # 함수 실행 전에 수행할 작업 print('함수실행전') # 원본 함수 호출 result = func() # 함수 실행 후에 수행할 작업 print('함수 실행 후') return result return wrapper
@my_decorator
def my_function(): print('원본 함수 실행')
my_function()
"""
함수 실행 전
원본 함수 실행
함수 실행 후
"""
절차 지향과 객체 지향은 대조되는 개념 X
기본은 절차 지향인데 보완을 위해 객체라는 개념 도입
⇒ 상속, 코드 재사용성, 유지보수성 등 이점을 가지는 패러다임
추가로 배운것

class는 붕어빵 틀, object는 붕어빵이름, instance는 붕어빵
인스턴스 변수는 클래스 메서드를 조작 할 수 있다.
클래스 변수는 인스턴스 메서드를 조작할 수
객체지향 프로그램의 4가지 특징
- 추상화 : 공통적이고 본질적인 특징을 추출하여 정의
- 상속 : 기존에 구현한 클래스를 재활용
- 다형성 : 같은 명령을 해도 다르게 결과가 나온다.
- 삼각형에게
그려라
⇒삼각형
을 그린다 - 원에게
그려라
⇒원
을 그린다.
- 삼각형에게
- 캡슐화 : 필요한 메서드만 보여주고 내부는 보여주지 않는다
메모리 구조
code
data 전역 // Class
heap 동적 // 인스턴스
stack 지역