<OOP, Module & Package>
7. Object-Oriented Programming
8. Module & Package
Object-Oriented Programming
절차 지향 프로그래밍(Procedure Programming)의 문제점
- 중간의 코드 수정 시, 모든 코드 수정이 필요할 수 있음
- 협업 시, 한 프로그래머의 수정 사항이 다른 프로그래머에게 영향
따라서, 코드를 객체 단위로 나누어 작성 및 분업해야 한다.
→ 객체 지향 프로그래밍
- 객체 단위 코드 작성 및 분업
- 각 Class당 Object가 하나만 존재하지 않는다
- 그러나 Object의 Attribute는 달라도 Method는 동일하다
Class 선언부 (Class Declaration)
class Courier (object): # (예약어) (클래스 명) (부모 클래스)
- Class 명은 CamelCase가 관습적으로 사용
- 부모 클래스가 지정되지 않았을 시, object가 자동 상속
Class 속성 (Class Attribute)
class Courier(object):
NATIONALITY = 'KOR'
- Class 전체가 공유하는 속성 값
- 모든 instance가 같은 값을 참조
- 남용하면 스파게티 코드의 원인이 됨
- 클래스.attribute 형태로 접근
print(Courier.NATIONALITY)
Class 함수 (Method)
class Courier:
def assign(self, parcel: str) -> None:
self.parcels.append(parcel)
- 각 객체에 적용이 가능한 함수
- 현재 수정하고자 하는 객체를 self로 지칭(관습)
- Python은 self를 첫 번째 파라미터로 명시적으로 받음
- Class.method(instance, args, ...) 혹은 instance.method(args, ...) 형태로 접근
courier1.assgin('TV 상자') # 메소드 실행
객체 속성 (Class Attribute)
class Courier(obeject):
def __init__(self, name: str, address: str):
self.name = name
- 각각의 instance가 개인적으로 가지는 값
- instance.attr 형태로 접근
- Class 형태로 선언되어 나온 객체는 언제 어디서든 attribute 수정 가능
Magic Method (__METHOD__)
생성자 (__init__)
class Courier(object):
def __init__(self, name: str, address: str):
self.name = name
self.address = address
self.parcels = []
- instance를 생성할 때 호출
- 일반적으로 instance의 속성을 초기화하는 데 사용
- class(args, ...) 형태로 호출하여 객체 생성
- 거의 유이하게 정해진 Argument format이 없는 Magic Method
소멸자 (__del__)
class Courier(object):
def __del__(self):
self.parcels.clear()
- 객체를 소멸할 때 호출
- 파이썬은 쓰레기 수거(Garbage Collection)로 메모리 관리
- instance가 어디에서도 참조되지 않을 때 객체가 소멸
- 소멸 타이밍을 잡기 어려워 잘 사용되지 않음
- del 명령어
- 변수 이름을 명시적으로 없애기 가능
- 참조를 명시적으로 삭제하는 것이지 객체를 명시적으로 삭제하는 것이 아님
OOP의 3요소 - Inheritance, Visibility, Polymorphism
상속 (Inheritance)
- 기존에 구현 틀 상속 → 새로운 틀 제작
- 기존의 틀: 부모 Class, 새로운 틀: 자식 Class
- 같은 기능을 재작성할 필요가 없음
- 다중 상속 지원
- 메소드 탐색 순서를 따름 (mro)
- super 내장 함수를 이용하여 상위 Class 접근 가능
class Courier(object): # (예약어) (클래스 명) (부모 클래스)
다형성 (Polymorphism)
- 같은 이름의 메소드를 다르게 작성
- 각 자식 Class가 다른 Class와 차별
- 부모 메소드로 접근 시 자식 메소드 실행
- 외부에서는 똑같은 API로 접근
- 고객 입장에서는 코드 수정이 없음
- Python에서는 동적 타이핑
- 고객 입장에서는 클래스 구분 x
- 같은 이름의 메소드가 있으면 실행 (Duck Typing)
Static & Class Method
- Static Method
- @staticmethod 꾸밈자 사용
- 특별한 argument를 받지 않음
- 일반적으로 Class 내 유틸 함수로 사용
- Class를 일종의 Namespace로 사용
- Class Method
- @classmethod 꾸밈자 사용
- 호출된 class인 cls를 받음 (self와 비슷)
- factory 패턴에서 사용
Visibility
- 다른 Class에게 Object의 내부를 감추기
- 캡슐화, 정보 은닉
- Class 간 간섭 최소화
- 최소한의 정보만을 지정된 API로 공개
- Python에서의 가시성
- 명시적인 private&proceed 범위가 없음 → 모두 public
- private 변수/함수 이름 앞에 "__"를 붙임 (밑줄 2개)
ex) self.__name
- protected 변수/함수 이름 앞에 "_"를 붙임 (밑줄 1개)
ex) self._name
Property
- Property를 통해 Getter, Setter를 명시적 설정 가능
- Encapsulation 등에 활용
class Circle(object):
PI * 3.141592
def __init__(self, radius=3.):
self.radius = radius
@property # Getter
def area(self):
return Circle.PI * self.radius ** 2
@area.setter # Setter
def area(self, value):
self.radius * (value / Circle.PI) ** 2
circle = Circle(5.)
print(circle.area)
circle.area = 10
print(circle.radius)
Indexing 메소드 (__getitem__, setitem__)
- Indexing을 재정의
def __getitem__(self, index): # Indexing get
return self.mapping.get(index, index * 2)
def __setitem__(self, index, item): # Indexing set
self.mapping[index] = item
Length 메소드 (__len__)
- Dataset 길이 반환
def __len__(self): # len(instance) 호출될 시 호출
return len(self.data) * self.times
dataset = Dataset([10, 2, 5, 2], times=5)
print(len(dataset)) # 20
Typing
- instance를 다른 타입으로 형 변환할 때 호출
- __str__, __int__, __float__, __bool__ 등이 존재
def __str__(self): #str 형변환
return self.address + ' 담당 ' + self.name
text = str(courier) # str 형변환 호출
Comparison Operator
- 비교 연산자 호출
__lt__(B): A < B
__le__(B): A <= B
__gt__(B): A > B
__ge__(B): A >= B
__eq__(B): A == B
__ne__(B): A != B
def __lt__(self, other): # '<' 연산자를 재정의
return self.cid < other.cid
Arithmetic Operator
__add__: 더하기 연산자 호출 (Out-place 버전)
__iadd__: 더하기 연산 자 호출 (In-place 버전)
→ self를 직접 수정 필요 (self.real += other.real)
__sub__: 빼기 연산자 호출
__mul__: 곱하기 연산자 호출
함수화 메소드 (__call__)
- 생성된 객체를 호출 가능하게 만듦
- instance(args, ...)가 instance.__call__(args, ...)를 호출
class AdditionNumber(object):
def __init__(self, number: int): # 생성자
self.number = number
def __call__(self, number: int): # 함수화 메소드
return number + self.number
addition_5 = AdditionNumber(5)
print(addition_5(10)) # instance를 함수처럼 사용
Iterable
seq = list([1, 2, 3, 4, 5])
# 실제 for 문 내부 동작 방식
iterator = iter(seq)
while True:
try:
elem = next(iterator)
except StopIteration:
break
print(elem)
- iter 내장함수
- 해당 객체의 순환자 반환
- __iter__ 호출
- next 내장함수
- 해당 순환자를 진행
- __next__ 호출
- 끝에서 StopIteration Exception
- Generator는 자동으로 __iter__와 __next__가 구현
Context Manager
class Courier:
courier = Courier("김 기사")
with courier: # enter()
courier.parcels.append("소포")
with courier("김 기사) as courier: # exist()
courier.parcels.append("소포")
- 소멸자 대용으로 특정 Block 입장/종료 시 자동으로 호출
- File description 등을 자동으로 닫고자 할 때 사용
Module & Package
다른 파일의 함수를 가지고 오고 싶다면?
- 다른 사람이 완성한 함수와 클래스 사용
- 내장 & 외부 라이브러리 사용
→ 모듈화가 필요
Import
- 파이썬에서 모듈 == .py 파일
- import 구문을 사용하여 모듈을 불러옴
- 해당 파일 최상위에 선언된 모듈의 요소들을 불러오기 가능
- module.element 식으로 사용
- . 혹은 .. 없이는 절대 경로 기준 (Python이 실행되는 곳)
- import 문은 import된 .py 파일을 처음부터 끝까지 실행
- 해당 모듈을 main으로 했을 때 특정 Block을 실행시키고 싶을 시,
if __name__ == "__main__":
print("이 코드는 functions 모듈이 메인일 때만 실행")
import directory.functions # 폴더 내 .py 파일
import directory.functions as func # as로 별칭 만들기
from directory import functions # from으로 특정 부분 import
from directory.functions import add # 특정 함수 import
from directory.functions import * # *로 모두 import
- 최상위에선 상대 경로가 작동되지 않음
- 최상위를 거치는 경우 포함
- 일반적으로 프로젝트 이름으로 폴더를 만들어 코드를 넣음
- 부모 폴더 접근을 위해서는 모듈 형태로 실행 필요
python -m test_nlp.dir1.sub_main
→ main을 module 형태로 실행
- '__init__.py': 폴더 import 시 초기화 가능
Conda를 이용하여 가상 환경 설정 (Virtual Enviromnet)
conda create -n 이름 # 가상 환경 만들기
conda activate 이름 # 가상 환경 활성화
conda deactivate # 가상 환경 나가기
conda install <패키지 이름> -c <설치 채널> #패키지 설치
- 채널이 명시되어 있지 않을 경우 default 채널 탐색
- 채널은 문서를 참고하거나 Anaconda Hub에서 검색
'Python' 카테고리의 다른 글
| Colab Runtime 유지 (0) | 2022.08.01 |
|---|---|
| I&O, Setting & Exception & Logging, Web (0) | 2022.05.01 |
| Advanced Data Structure & String (0) | 2022.04.28 |
| Python Programming (0) | 2022.04.26 |
| Python Basic (0) | 2022.04.25 |