네이버 부스트코스에서 제공하는 최성철 님의 강의를 참고하여 작성된 포스팅입니다.
객체 지향 프로그래밍 (Object-Oriented Programming)
만들어 놓은 코드를 재사용하기 위해 클래스, 객체를 다룬다
- 객체 : 속성 (variable), 함수(method) 로 구성됨
- 파이썬 역시 객체지향 언어
- class : 설계도, 틀
- instance : class로 구현한 실체
class SoccorPlayer(object): # object : 상속받는 객체명
def __init__(self, name, back_number):
self.name = name
self.back_number = back_number
def change_back_number(self, new_number):
print(f'선수 등번호 변경 {self.back_number} to {new_number}')
self.back_number = new_number
클래스 밖에서도 속성 값 변경이 가능하나 이를 권장하지는 않음
- 함수 작성 스타일
- snake_case : 띄어쓰기 부분에 ‘_’, 함수/변수명
- CamelCase : 띄어쓰기 부분에 대문자, class 명
attribute
- __init__ : 객체 초기화 예약 함수
- __ : 특수한 예약함수, 변수, 함수명 변경(맨글링)으로 사용
- __main__ , __add __ , __ str __ , __ eq __ : 매직 메서드
- 파이썬 더블 언더스코어: Magic Method | Corikachu
- __ init __ 은 반드시 self를 첫번째 인자로 사용해야 함 (self: 생성된 인스턴스 자신을 의미)
- [python] python의 self와 init의 이해
method
기존 함수와 같이 추가하되, 반드시 파라미터 첫 번째 인자에 ‘self’를 추가해야 클래스 함수가 됨
객체 지향 언어의 특징 및 구성요소
상속 (Inheritance)
부모 클래스로부터 속성, 메서드를 물려받은 자식 클래스 생성
# 초기 상속 default : object
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def about_me(self):
print(f"이름은 {self.name}, 나이는 {self.age}")
class Korean(Person): # person 클래스로부터 상속받음
pass
first_korean = Korean("Sungchul", 35)
print(first_korean.name) # "Sungchul", 부모 클래스에서 상속받은 값 그대로
새로운 메서드 추가나 부모 클래스 함수 재정의도 가능
class Employee(Person):
def __init__(self, name, age, gender, salary, hire_date):
super().__init__(name, age, gender) # 부모 객체를 사용
self.salary = salary
self.hire_date = hire_date
def do_work(self):
print("일하기")
def about_me(self): # 부모 클래스 함수 재정의
print(f"이름 {self.name}, 급여 {self.salary}, 입사일 {self.hire_date}")
다형성 (Polymorphism)
같은 이름 메소드의 내부 로직을 다르게 작성
Dynamic Typing 특성으로 인해 파이썬에서는 같은 부모 클래스의 상속에서 주로 발생
💡 개념은 같은데 세부적인 구현이 다를 때!
함수 명은 같은데 안의 인터페이스 ,코드에 따라서 조금씩 다르게 코드를 짤 수 있는 것
# 상위 클래스인 Animal 에서 abstract method만 구현
class Animal:
def __init__(self,name):#Constructor of the class
self.name =name
def talk(self):#Abstract method,defined by convention only
raise NotImplementedError("Subclass must implement abstract method")
# 하위 클래스에서 상위 클래스의 추상 메서드를 구체화
class Cat(Animal):
def talk(self):
return 'Meow!'
class Dog(Animal):
def talk(self):
return 'Woof!Woof!'
animals =[Cat('Missy'), Cat('Mr.Mistoffelees'), Dog('Lassie')]
for animal in animals:
print(animal.name +':'+animal.talk())
가시성(Visability)
객체의 정보를 볼 수 있는 레벨을 조절하는 것
임의의 사용자가 정보를 수정하는 것을 방지하거나 제품 판매 시 소스 보호
캡슐화 (Encapsulation)
클래스 설계 시 클래스 간 간섭/ 정보공유 최소화
인터페이스만 알면 쓸 수 있음
개념적으로 정보를 분리 → 코딩 실수 줄여
다음과 같은 상황을 가정해보자.
- Product 객체를 Inventory 객체에 추가
- Inventory에는 오직 Product 객체만 들어감
- Inventory에 Product가 몇 개인지 확인이 필요
- Inventory에 Product items 접근 불가
class Product(object):
pass
class Inventory(object):
def __init__(self):
# 언더바 두개 : private 변수
self.__items =[]
def add_new_item(self,product):
if type(product)==Product:
self.__items.append(product)
print("new item added")
else:
raise ValueError("Invalid Item")
def get_number_of_items(self):
return len(self.__items)
my_inventory =Inventory()
my_inventory.add_new_item(Product())
my_inventory.add_new_item(Product())
print(my_inventory.get_number_of_items())
print(my_inventory.__items)
my_inventory.add_new_item(object)
#################
new item added
new item added
2
Traceback (most recent call last):
File "c:\Users\hwyew\Downloads\boostcamp\test2.py", line 22, in <module>
print(my_inventory.__items)
^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Inventory' object has no attribute '__items'
이런 식으로 작성하면 밖에서 product items에 직접 접근이 불가함
다음과 같은 상황을 가정해보자.
- Product 객체를 Inventory 객체에 추가
- Inventory에는 오직 Product 객체만 들어감
- Inventory에 Product가 몇 개인지 확인이 필요
- Inventory에 Product items 접근 허용
class Product(object):
pass
class Inventory(object):
def __init__(self):
self.__items =[]
@property
def items(self):
return self.__items
def add_new_item(self,product):
if type(product)==Product:
self.__items.append(product)
print("new item added")
else:
raise ValueError("Invalid Item")
def get_number_of_items(self):
return len(self.__items)
my_inventory =Inventory()
my_inventory.add_new_item(Product())
my_inventory.add_new_item(Product())
print(my_inventory.get_number_of_items())
items =my_inventory.items
items.append(Product())
print(my_inventory.get_number_of_items())
#######################
new item added
new item added
2
3
@property 데코레이터 이용하면 외부에서는 접근이 안되지만, 내부에서는 접근이 가능해서 반환할 수 있게 해줌
단, 그대로 반환하면 외부에서 값 수정도 가능해지므로 보통은 copy해서 반환함
decorate
- first-class objects : 일등 함수, 일급 객체
- 변수나 데이터 구조에 할당이 가능한 객체
- 파라미터로 전달 가능 + 리턴 값으로 사용
- 파이썬의 함수는 일급함수
- map(f, ex) : 함수가 파라미터처럼 쓰임
def square(x):
return x*x
f = square
f(5)
def square(x):
return x * x
def cube(x):
return x*x*x
def formula(method,argument_list):
return [method(value)for value in argument_list]
- inner function : 함수 내 또 다른 함수
- closures : inner function을 return값으로 반환
- 파이썬은 일급함수이기 때문에 함수 자체를 return 가능!
- 비슷한 목적을 가진 함수를 다양하게 만들 수 있음
-
def print_msg(msg): def printer(): print(msg) return printer another =print_msg("Hello,Python") another() ################# def tag_func(tag,text): text =text tag = tag def inner_func(): return '<{0}>{1}<{0}>'.format(tag,text) return inner_func h1_func=tag_func('title' ,"This is Python Class") p_func =tag_func('p' ,"DataAcademy")
- closures : inner function을 return값으로 반환
- decorator : 복잡한 클로저 함수를 간단하게 만들 수 있다
- printer 함수가 star 함수 안에 들어감
def star(func):
def inner(*args,**kwargs):
print("*" *30)
func(*args,**kwargs)
print("*" *30)
return inner
@star
def printer(msg):
print(msg)
printer("Hello")
def generate_power(exponent):
def wrapper(f):
def inner(*args):
result =f(*args)
return exponent**result
return inner
return wrapper
@generate_power(2) # 값을 넣어줄 수도 있음
def raise_two(n): # wrapper(f)에 들어감
return n**2
4-2. 모듈과 프로젝트
모듈을 모아 하나의 큰 프로그램 개발 → 다른 사람이 이해하고 사용하기 쉬워짐
패키지 : 모듈을 모아 놓은 단위, 하나의 프로그램
- 파이썬에서는 모듈 == py 파일
namespace
- 모듈을 호출할 때 범위를 정하는 방법
- 필요한 내용만 골라서 호출 (from ~ import ~)
- 독자 입장에서는 읽기 힘들 수 있음. 어디서 import 했는지 명시해주는 게 좋을 수 있다.
- alias 설정 가능 (import ~ as ~)
- 좋은 코드를 위해서는 import * 하는 습관을 줄이자!
package
하나의 대형 프로젝트를 만드는 코드 묶음
- 다양한 모듈들의 합, 폴더로 연결됨
- init, main 같은 키워드 파일명 사용됨
- 폴더별로 **init.py 구성**
- 현재 폴더가 패키지임을 알리는 초기화 스크립트 → 없을 경우 패키지로 간주하지 않음 (3.3+부터는 없어도 되긴 하지만 관습적으로 함)
- 하위 폴더와 py 파일 (모듈)을 모두 포함
- import, all 키워드 사용
-
# game/init.py -> 각 폴더마다 생성 __all__=['image','stage','sound'] # 앞으로 쓸 하위폴더 모듈들의 이름을 적음 # 전부 호출 from . import image from . import stage from . import sound # image/init.py __all__=['character','object_type'] # 전부 호출 from . import character from . import object_type
- main.py 만들기 : 폴더 자체를 불러와서 패키지 이름만으로 호출 가능
-
from stage.main import game_start from stage.sub import set_stage_level from image.character import show_character from sound.bgm import bgm_play if __name__=='__main__': game_start() set_stage_level(5) bgm_play(10) show_character()
- 구성 이후에는 패키지 이름만으로 호출 가능
패키지 namespace
- 절대 참조
from game.graphic.render import render_test()
- 상대 참조
# . : 현재 디렉토리 기준 # .. : 부모 디렉토리 기준 from .render import render_test() from ..sound.echo import echo_test()
'NLP > AI 이론' 카테고리의 다른 글
[AI Math] 벡터와 행렬의 개념 (1) | 2024.01.28 |
---|---|
[Python] NumPy & Pandas (1) | 2024.01.28 |
[Python] Python Data Handling (1) | 2024.01.28 |
[Python] Python File/Exception/Log Handler (2) | 2024.01.28 |
[Python] 파이썬이란? (1) | 2024.01.28 |