수강신청 프로그램 작성
두 가지 모두 가능, 최근에는 방법2가 주류, 이러한 기법을 객체 지향 프로그램이라 한다.
- Object-Oriented Programming(OOP)
- Object : 실생활에서 일종의 물건, 속성(Attribute)와 행동(Action)을 가짐
- OOP는 이러한 객체 개념을 프로그램으로 표현
속성은 변수(Variable), 행동은 함수(Method)로 표현됨- Python역시 OOP Language
ex) 인공지능 축구 프로그램을 작성한다고 가정
- 객체 종류 : 팀, 선수, 심판, 공
- Action : 선수(공을 차다, 패스하다), 심판(휘슬을 불다, 경고를 주다)
- Attribute : 선수(선수 이름, 포지션, 소속팀), 팀(팀 이름, 팀 연고지, 팀소속 선수)
축구 선수 정보를 Class로 구현해보자.
class SoccerPlayer(object):
def __init__(self, name, position, back_number):
self.name = name
self.position = position
self.back_number = back_number
def change_back_number(self, new_number):
print("선수의 등번호를 변경합니다 : From %d to %d" % (self.back_number, new_number))
self.back_number = new_number
- Variable, Class, Function 이름은 짓는 방식이 존재
- Snake_case : 띄어쓰기 부분에 언더바 추가
뱀처럼 늘여쓰기, Python Function/Variable명으로 사용- CamelCase : 띄어쓰기 부분에 대문자
낙타의 등 모양, Python Class명으로 사용
#__init__(객체 초기화 예약 함수), self 사용
class SoccerPlayer(object):
def __init__(self, name, position, back_number):
self.name = name
self.position = position
self.back_number = back_number
ex) __main__, __add__, __str__, __eq__
class SoccerPlayer(object):
def __init__(self, name, position, number):
self.name = name
self.position = position
self.number = number
def __str__(self):
return "Hello, My name is %s. I play in %s in center " % (self.name, self.position)
jinhyun = SoccerPlayer("Jinhyun", "MF", 10)
print(jinhyun)
class ScoccerPlayer(object):
def change_back_number(self, new_number):
print("선수의 등번호를 변경합니다 : From %d to %d" %(self.back_number, new_number))
self.back_number = new_number
Object(Instance) 사용하기
: Object명 선언과 함께 초기값 입력하기
Class 구현하기
class SoccerPlayer(object):
def __init__(self, name, position, back_number):
self.name = name
self.position = position
self.back_number = back_number
def change_back_number(self, new_number):
print("선수의 등번호를 변경합니다 : From %d to %d" % (self.back_number, new_number))
self.back_number = new_number
jinhyun = SoccerPlayer("Jinhyun", "MF", 10)
print("현재 선수의 등번호는 :", jinhyun.back_number)
jinhyun.change_back_number(5)
print("현재 선수의 등번호는 :", jinhyun.back_number)
현재 선수의 등번호는 : 10
선수의 등번호를 변경합니다 : From 10 to 5
현재 선수의 등번호는 : 5
구현 가능한 OOP 만들기 - Notebook
Class Scheme
Note Class
class NoteBook(object):
def __init__(self, title):
self.title = title
self.page_number = 1
self.notes = {}
def add_note(self, note, page=0):
if self.page_number < 300:
if page == 0:
self.notes[self.page_number] = note
self.page_number += 1
else:
self.notes[page] = note
self.page_number += 1
else:
print("Page가 모두 채워졌습니다.")
def remove_note(self, page_number):
if page_number in self.notes.keys():
return self.notes.pop(page_number)
else:
print("해당 페이지는 존재하지 않습니다")
def get_number_of_pages(self):
return len(self.notes.keys())
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
class Korean(Person):
pass
first_korean = Korean("Sungchul", 35)
print(first_korean.name)
ex)
class Person(object): # 부모 Class Person 선언
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def about_me(self): # Method 선언
print("저의 이름은 ", self.name, "이구요, 제 나이는 ", str(self.age), "살 입니다.")
ex2)
class Employee(Person): # 부모 Class 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): # 새로운 Method 추가
print("열심히 일을 합니다.")
def about_me(self): # 부모 Class 함수 재정의
super().about_me() # 부모 Class 함수 사용
print("제 급여는 ", self.salary, "원 이구요, 제 입사일은 ", self.hire_date," 입니다.")
ob1 = Employee("lilmeow", 24, "male", 100, "1월 11일")
print(ob1)
ob.about_me()
<__main__.Employee object at 0x10391bb50>
저의 이름은 lilmeow 이구요, 제 나이는 24 살 입니다.
제 급여는 100 원 이구요, 제 입사일은 1월 11일 입니다.
- 같은 이름 Method의 내부 Logic을 다르게 작성
- Dynamic Typing 특성으로 인해 Python에서는 같은 부모 Class의 상속에서 주로 발생함
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())
Missy: Meow!
Mr. Mistoffelees: Meow!
Lassie: Woof! Woof!
Visibility
- Object의 정보를 볼 수 있는 Level을 조절하는 것
- 누구나 Object 안에 모든 변수를 볼 필요가 없음 :
1. Object를 사용하는 사용자가 임의로 정보 수정
2. 필요 없는 정보에는 접근 할 필요가 없음
3. 만약 제품으로 판매한다면? 소스의 보호
Encapsulation
- 캡슐화 또는 정보 은닉 : Information Hiding
- Class를 설계할 때, Class 간 간섭/정보 공유의 최소화
- 심판 Class가 축구선수 Class 가족 정보를 알아야 하나?
- 캡슐을 던지듯, Interface만 알아서 써야함
Visibility Example1.
- Product Object를 Inventory Object에 추가
- Inventory에는 오직 Product Object만 들어감
- Inventory에 Product가 몇 개인지 확인이 필요
- Inventory에 Product items는 직접 접근이 불가
class Product(object):
pass
class Inventory(object):
def __init__(self):
self.__items = [] # Private Variable로 선언 타객체가 접근 못함
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)
class Inventory:
def __init__(self):
self.__items = []
def add_new_item(self, item):
self.__items.append(item)
def get_number_of_items(self):
return len(self.__items)
class Product:
pass
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._Inventory__items)
my_inventory.add_new_item(object)
2
[<__main__.Product object at 0x1033891b0>, <__main__.Product object at 0x10338a290>]
- Product Object를 Inventory Object에 추가
- Inventory에는 오직 Product Object만 들어감
- Inventory에 Product가 몇 개인지 확인이 필요
- Inventory에 Product items 접근 허용
class Inventory(object):
def __init__(self):
self.__items = []
@property # Property Decorator : 숨겨진 Variable를 Return하게 해준다
def items(self):
return self.__items
def add_new_item(self, item):
self.__items.append(item)
def get_number_of_items(self):
return len(self.__items)
class Product(object):
pass
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 # Property Decorator로 Function을 Variable처럼 호출
items.append(Product())
print(my_inventory.get_number_of_items())
class Student:
def __init__(self, name, marks):
self.name = name
self.marks = marks
# self.gotmarks = self.name + ' obtained ' + self.marks + ' marks'
@property
def gotmarks(self):
return self.name + ' obtained ' + str(self.marks) + ' marks'
- 일등함수 또는 일급 Object
- Variable이나 Data Structure에 할당이 가능한 Object
- Parameter로 전달이 가능 +Return 값으로 사용
- Python Function = 일급함수
def square(x):
return x * x
f = square # Function을 Variable로 사용
f(5) # 25
def square(x):
return x * x
def cube(x):
return x * x * x
def formula(method, argument_list): # Function을 Parameter로 사용
return [method(value) for value in argument_list]
def print_msg(msg):
def printer():
print(msg)
printer()
print_msg("Hello, Python") # Hello, Python
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', "Data Academy")
def star(func):
def inner(*args, **kwargs):
print("*" * 30)
func(*args, **kwargs)
print("*" * 30)
return inner
@star
def printer(msg):
print(msg)
printer("Hello")
******************************
Hello
******************************
def star(func):
def inner(*args, **kwargs):
print("*" * 30)
func(*args, **kwargs)
print("*" * 30)
return inner
def percent(func):
def inner(*args, **kwargs):
print("%" * 30)
func(*args, **kwargs)
print("%" * 30)
return inner
@star
@percent
def printer(msg):
print(msg)
printer("Hello")
******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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):
return n**2
print(raise_two(7)) # 562949953421312