1. OOP란?
- OOP : Object Oriented Programming 의 약자로, `객체 지향 프로그래밍’ 이라 한다.
- Object(객체) : 소프트웨어로 구현할 대상
- OOP의 특징: Encapsulation(캡슐화) 로 ‘attribute’ 와 ‘method’를 하나로 묶어서 객체로 구성하는 것
- ‘OOP’의 이점
Encapsulation(캡슐화)
를 통해서 내부 정보를 외부로부터 보호하면서,주변에 악영향 (side effect)
을 최소화할 수 있다. 이를Infomation hiding(정보 은폐)
이라 한다.- class를 통해 만들기 때문에
코드의 재사용성
이 용이하다. =>경제적
- 코드의 개선, 수정이 용이하다.
- 버그가 발생했을 때 유지보수 또한 용이하다.
- 하지만, ‘OOP’가 항상 빠르진 않다. 경우에 따라서는
객체 지향
보다절차 지향
이 더 빠른 퍼포먼스를 가질 수 있으므로,객체 지향
과절차 지향
을 적절히 섞어 사용하자.절차 지향
: 위에서부터 아래로 실행하는 것
절차지향과 OOP 비교해보기 : [TIL] Python basic 24: Procedural Programming vs OOP
2. Class와 instatnce의 차이
- 눈에 보이는 ‘실체’들 중에서 ‘소프트웨어로 구현할 대상`‘을 선정한다.
- 소프트웨어로 구현할 대상을
객체(Object)
라 한다.
- 소프트웨어로 구현할 대상을
- 이 객체(Object) 를 class라는 틀 을 통해서 소프트웨어적으로 묘사한 것을 instance 라 한다.
2.1 Class 만들고 호출하기
class 만들기 위한 상황
- 애완견 용품에서 사용하는 소프트웨어를 개발한다고 가정하자.
- 개의 종은 매우 다양해서 개의 종이 추가될 때마다 변수 입력한다면 그 양이 매우 많아지고 가독성도 떨어진다.
- 하지만, 클래스를 이용한다면 눈에 보이는 애완견 실체를
클래스 형태
로 구성해서instance
로 만들 수 있다. - 즉 클래스는 설계도라고 생각하면 되고, 인스턴스(instance)는 이 설계도를 토대로 만들어진 것이라 생각하자.
class
라는 예약어를 통해 클래스를 만들기 시작한다.- 모든 클래스는 object를 상속받기 때문에, 선언 방법은 자유롭다.
__init__
에 대해서- 파이썬에서 클래스가 초기화될 때 반드시 호출되는 함수다. 반드시 호출되는 이유는 개발자가 초기화 작업을 잊을 경우, 예상치 못한 오류가 발생할 수 있다. 예를 들어 의도한 대로라면 특정 정보를 가지고 있어야 하는데 아무런 정보를 가지고 있지 않아 오류가 발생할 수 있다. 그래서 ‘반드시’ 초기화 작업을 해야 한다.
- 사용자가 스스로 ‘__init__’ 사용자 정의 생성자를 만들지 않아도 ‘__init__’ 이 없으면 파이썬이 알아서 클래스를 만들 때 내부적으로 실행한다.
|
|
- 클래스 정보를 호출해보자.
|
|
2.2 인스턴스화하기
‘인스턴스화’란 class를 통해 구현된 instance에 변수를 할당하는 걸 의미하는데, 인스턴스화한 변수들은 모두 다른 id값을 가진다. 즉 각 인스턴스는 고유의 것이다.
instance
는 변수에 할당하여 활용되며, 이는 메모리에 올라가서 각각의 다른id
값을 가진다. 전혀 다른 객체로 간주된다.- 또한, 각 instance는 동일한 속성값을 가져도, 파이썬에게는 전혀 다른 객체로 간주된다.
|
|
2.3 namespace 확인하기
namespace란 python의 해당 객체와 관련된 attribute의 name들이 저장된 공간 으로서, dictionary가 python의 naming system에 사용하기 때문에, 각 name은 key로서 중복되지 않는다.
dir()
과.__dict__
를 통해서 namespace를 확인할 수 있는데, 그럼 이 두 가지의 차이는 무엇일까??dir( ) .__dict__ function or method built-in function(내장함수) magic method(special method) Data type list dictionary 호출 내용 객체를 만든 class가 가진 attribute와 method 정보 ( key name만 ) 인스턴스 객체만의 attribute와 value ( key name과 value )
|
|
- namespace 를 통해서 class와 instance들이 가지고 있는 속성들을 확인할 수 있다.
- class 는 하나지만, instance를 만들 때 다른 속성 값을 입력했기 때문에,
dir()
이 아닌,.__dict__
를 통해서 이를 확인할 수 있다. 그래서 instance의 속성값을 확인할 때는.__dict__
를 사용하자.
3. Self 의 이해: class method, instance method
- class method : 클래스 변수를 인자로 받는 method
- instance method : 인스턴스 변수를 인자로 받는 method
- self : instance를 인자로 받는 매개변수
method 호출방법
- class method 1가지 방법
- ❗️ 주의 사항: 인스턴스화한 변수를 통해서 class method 를 호출하면 error가 뜬다.
- class로 바로 호출하는 방법 (1-1 방법)
- instance method 2가지 방법
- 첫 번째: 인스턴스화 변수를 통해서 instance method 를 호출하는 방법 (2-1 방법)
- 두 번째: 클래스로 접근하여 인자에 인스턴스를 넘겨주는 방법 (2-2 방법)
instance 변수를 만들지 않고 사용할 것이기 때문에, ‘__init__’ 사용자 정의 생성자를 만들지 않는다 ‘__init__’ 이 없으면 파이썬이 알아서 클래스를 만들 때 내부적으로 실행한다.
|
|
인스턴스화된 f를 통해서 func1을 호출해보자. func1에는 매개변수가 없는데, 1개가 넘어갔다는 걸 알 수 있다.
|
|
func1은 매개변수가 없는데, 왜 매개변수로 1개가 넘어간 것일까? 넘어간 매개변수는 무엇일까??
- 바로 인스턴스가 인자로 넘어간 것이다. 인스턴스에 dot operator로 class의 method에 접근하면 인스턴스가 인자로 넘어가기 때문에, 위와 같은 TypeError가 발생했다.
인스턴스 메서드 호출 방법: 2-1
2-1 방법으로 인스턴스화된 f를 통해서 func2를 호출해보자.
|
|
- 위 결과를 통해서 다음과 같은 이유로 self는 instance를 인자로 받는 매개변수 이며, self가 있는 method 는 instance의 method 인 걸 알 수 있다.
- 첫 번째, func1을 호출한 방법과 동일한 방법으로 self가 매개변수로 있는 func2를 호출하니 Error가 뜨지 않았다.
- 두 번째,
f.func2()
에 의해서 출력된id
와id(f)
의 값이 동일하다.
클래스 메서드 호출 방법: 1-1
1-1 방법으로 class method를 호출해보자.
|
|
- 위 결과를 통해서 다음과 같은 이유로 self가 없는 method 는 class method인 걸 알 수 있다.
func1
을 인스턴스로 접근하여 호출했을 때는 TypeError가 떴었다.- 하지만, class로 직접 접근하여 호출하니, 정상적으로 출력된 걸 알 수 있다.
만약 class로 접근하여 func2를 호출한다면 어떻게 될까???
|
|
func2가 요구하는 매개변수 1개를 놓쳤다는 TypeError를 확인할 수 있다.
인스턴스 메서드 호출 방법: 2-2
그러면 2-2 방법으로 매개변수 1개를 입력해보자.
|
|
그래서 클래스로 접근해도 instance method에 인스턴스화한 변수를 인자로 넘기니 정상적으로 작동됨을 알 수 있다.
4. class, instance variable
다른 클래스를 만들어보자.
instance attribute
를 만들어서 사용할 것이기 때문에 사용자 정의 생성자를 위해__init__
를 사용한다.그리고
생성자
와는 반대로소멸자
를 사용했다.소멸자
: 객체가 소멸될 때 즉, 메모리에서 지워질 때 자동으로 호출되는 함수
|
|
4.1 class 속성, instance 속성 확인하기
namespace에는 객체의 속성들이 있는 곳임을 확인했다. 그러면 class와 instance의 각 속성들을 한층 더 들어가 확인해보자.
Class variable(클래스 변수)
- class 내부 method를 정의하기 전인 enclosing-scope에 정의한 변수
- 현재 상태로는 직접 접근이 가능하다. 접근 제어자라는 개념을 나중에 학습하면 접근 권한을 차등적으로 변수마다 부여할 수 있다.
- 클래스 변수는 공유되기 때문에, 모든 인스턴스에서 공통으로 가지고 있는 변수
- instance의 namespace에 있지 않고, class의 namespace에 존재한다.
instance variable(인스턴스 변수)
self
가 붙은 것들이instance varible(인스턴스 변수)
다.- 직접 접근이 아닌, 인스턴스화된 변수로 접근이 가능하다.
- 객체마다 별도로 존재한다.
namespace
라는 인스턴스만의 공간 을 별도로 갖고 있어서, namespace를 통해 인스턴스 변수를 확인한다.
클래스 변수에 접근하기
class name으로 접근하기
인스턴스화된 변수를 통해서 접근하기
1 2 3 4 5 6 7
# 클래스로 직접 접근하기 > print(Warehouse.stock_num) 2 # 인스턴스화된 변수를 통해서 접근하기 > print(user1.stock_num) 2
- 직접 접근이 가능하며, 모든 인스턴스가 공유한다는 걸 알 수 있다.
인스턴스 변수에 접근하기
- 인스턴스화된 변수를 통해서 접근하기
|
|
클래스 변수와 인스턴스 변수 확인하기
class와 instance의 각 namespace에서 class 변수와 instance 변수를 확인해보자.
|
|
위 코드를 통해서 다음을 알 수 있다.
- 클래스 변수는 인스턴스의 공통된 변수이지만, 인스턴스의 네임스페이스에서는 찾을 수 없다.
- 클래스 변수는 클래스의 네임스페이스에서 찾을 수 있다.
소멸자를 사용하여 instance를 삭제하면, 클래스 변수인 stock_num이 감소한 걸 확인할 수 있다.
1 2 3
> del user1 > print('after', Warehouse.__dict__) {'__module__': '__main__', 'stock_num': 1, ...}
4.2 Python의 namespace lookup 원리
파이썬은 object의 이름을 다음 순서로 찾는다.
super class는 해당 class의 상위 class를 의미한다.instance
의 namespace ->class
의 namespace ->super
의 namespace
한 가지 의문
instance의 namespace에서는 class 변수가 없다.
그러면 인스턴스화한 변수를 통해서 클래스 변수가 어떻게 출력되는걸까???
이는 python이 instance의 namespace에서 찾지 못하면 class의 namespace에서 찾아 출력한다.
5. Class의 장점
마지막으로 또 다른 클래스를 만들어보면서 위 내용들을 음미해보자.
|
|
위 예제들을 통해서
class
의 장점을 다시 한 번 확인할 수 있다.class
하나를 만들어놓고 찍어내듯이 사용할 수 있다.instance
만의 공간도 있고, 공유하는 공간이 있다.- 그래서
코드의 재사용성
이 좋다는 것이다.
코드의 재사용성
이 좋다는 의미는 더 구체적으로 말하자면- 객체지향에 입각하여 불필요한 중복을 방지한다.
- 깔끔한 코드를 통해 프로그램 개발을 할 수 있다.
- 생산성이 향상되고, 성능도 코드에 따라 좋아진다.
Summary
namespace: 파이썬의 객체들과 관련된 속성들이 dictionary 형태로 저장된 공간
dir과
__dict__
의 차이점dir( ) .__dict__ function or method built-in function(내장함수) magic method(special method) Data type list dictionary 호출 내용 객체가 가진 속성 name과 method 정보 ( key name만 ) 객체의 속성 name과 name의 value까지 ( key name과 value ) method의 종류: class method, instance method, static method
인스턴스의 namespace에는 class 변수는 존재하지 않지만, 인스턴스를 통해서 접근할 수 있다. 그 이유는 인스턴스의 namespace에서 찾지 못하면 class의 namespace에서 찾기 때문이다.
인스턴스화된 변수를 통해서는 클래스 메서드에 접근할 수 없다.
클래스 메서드에 접근하기 위해서는 클래스를 통해서 바로 접근해야 하며, 인스턴스 메서드에 접근하기 위해서는 인스턴스화된 변수를 통한 방법과 클래스로 접근하여 인자에 인스턴스를 넘겨주는 방법이 있다.