Python 이란?
- 1990년 암스테르담의 귀도 반 로섬(Guido Van Rossum)이 개발한 인터프리터(Interpreter) 언어
- 고대 신화에 나오는 파르나소스 산의 동굴에 살던 큰 뱀 (파이썬 표지와 아이콘이 뱀 모양)
- 다양한 라이브러리들과 통합환경의 동시 제공 (numpy, pandas 등)
- 관련 서비스
- 파일 동기화 서비스 드롭박스(Dropbox)
- Web 개발 프레임워크 장고(Django/Flask)
- 머신러닝/딥러닝 라이브러리(Sklearn, tensorflow, mxnet, pytorch..)
Python 특징
Interpreter 기반의 객체 지향 언어
- 바이트 코드 컴파일을 지원하는 동적 인터프리팅 언어 (.py > .pyc)
- python shell 에서 interpreter 모드 테스트 가능
플랫폼 독립적 언어
- Windows, MAC OS, Palm OS, Android, Unix 계열, Linux 계열 등 다양한 OS 지원
유연한 확장
- 컴파일된 외부 모듈을 인터프리터 내부로 동적로딩 지원
동적 타이핑
- 컴파일 시점이 아닌 프로그램 실행 시점에 Type Checking 을 수행
- 개발생산성 향상 가능
- 디버그 속도 저하 발생 가능
리플렉션 (Reflection)
- Runtime 시 객체에 대한 상세 정보 획득 가능
- Object Properties 조작 가능
쉬운 문법, 빠른 속도
- 프로그램의 뼈대는 파이썬으로 짜고 빠른 실행속도를 필요로 하는 부분은 C 로 구현하여 import 가능
- Python 의 많은 라이브러리가 C 로 구현됨
간결함
- { } (브레이스) 없이 들여쓰기를 통해 단락 구분
- 강제적인 인덴테이션으로 가독성 향상
OOP - Classes and Instances
일반적인 클래스 정의
class Employee: pass # do nothing emp_1 = Employee() emp_2 = Employee() # emp_1, emp2는 클래스(Employee)의 인스턴스, 주소 다름
인스턴스 변수 설정
emp_1.first = "kildong" emp_1.last = "hong" emp_1.email = "kildong.hong@gmail.com" emp_1.pay = 100
설정 값 확인
print('{} / {}'.format(emp_1.email, emp_1.first))
Class Variables 클래스 변수
클래스 전역 변수
- cls 지시자를 통해 access 가능
인스턴스 변수는 self 지시자를 통해 access
class Employee: raise_amount = 1.04 def __init__(self, first, last, pay): self.first = first self.last = last self.pay = pay self.email = first + '.' + last + '@email.com' emp_1 = Employee('killdong', 'hong', 10000) emp_2 = Employee('chunhang', 'sung', 2000) # raise_amount - 클래스 변수 # first, last, pay, email - 인스턴스 변수 // 클래스 변수 값을 변경하면 해당 인스턴스의 값이 전부 변경된다. Employee.raise_amount = 1.05 print(emp_1.raise_amount) # 1.05 print(emp_2.raise_amount) # 1.05 print(Employee.raise_amount) # 1.05 // 인스턴스 변수에 대한 값을 변경하면 클래스 변수의 raise_amount 는 바뀌지 않는다. emp_1.raise_amount = 1.06 print(emp_1.raise_amount) # 1.06 print(emp_2.raise_amount) # 1.05 print(Employee.raise_amount) # 1.05
Static Method and Class Method
Instance Method
- 일반적인 메소드 형태
- parameter 는 self 부터 시작 (instance 의미)
Class Method
- @classmethod annotation 으로 접근가능
- parameter 는 cls 부터 시작 (class 의미)
Static Method
- @staticmethod annotation 으로 접근가능
- method parameter 에 self, cls 없음
- util 성 메소드 작성에 적합
- class, instance를 통해서 접근 가능하나 되도록 class 를 통해 호출하는 것이 바람직
class Employee: raise_amount = 1.04 num_of_emps = 0 ### instance개수를 담을 class variables def __init__(self, first, last, pay): self.first = first self.last = last self.pay = pay self.email = first + '.' + last + '@email.com' Employee.num_of_emps += 1 ## instance개수를 +1씩 증가시킨다. def fullname(self): return '{} {}'.format(self.first, self.last) def apply_raise(self): self.pay = int(self.pay * self.raise_amount) #Instance Variables는 'self.변수명'으로 접근 가능 # class method선언은 @classmethod annotation을 사용하고 # 메소드 파라미터의 첫인자는 cls를 기본적으로 설정한다. @classmethod def set_raise_amt(cls, amount): cls.raise_amount = amount @classmethod def from_string(cls, emp_str): first, last, pay = emp_str.split('-') #return Employee(first, last, pay) # __init__ parameter와 같은 순서로 객체를 생성하라. return cls(first, last, pay) #static method는 별도의 parameter를 전달하지 않는다. # weekday()는 '0:월, 1:화, 2:수, 3:목, 4:금, 5:토, 6:일'의 값을 리턴 @staticmethod def is_workday(day): if day.weekday() == 5 or day.weekday() == 6: return False return True # class method를 통해서 class variables를 변경한다. Employee.set_raise_amt(1.05) # class method를 통한 instance 생성 new_emp_1 = Employee.from_string(emp_str_1) new_emp_2 = Employee.from_string(emp_str_2) #static method 호출 > class를 통해 접근 import datetime my_date = datetime.date(2016, 7, 11) print(Employee.is_workday(my_date)) # instance를 통해서도 호출은 가능하나, class를 통해서 호출하는 것이 바람직. new_emp_1.is_workday(datetime.date(2018, 6, 2))
Inheritance-Subclasses
- 부모 클래스의 속성/메소드와 같은 속성/메소드를 자식 클래스에서 재정의 가능
class Employee: raise_amount = 1.04 def __init__(self, first, last, pay): self.first = first self.last = last self.pay = pay self.email = first + '.' + last + '@email.com' def fullname(self): return '{} {}'.format(self.first, self.last) def apply_raise(self): self.pay = int(self.pay * self.raise_amount) #Instance Variables는 'self.변수명'으로 접근 가능 #Employee를 상속하는 자식클래스를 선언 class Developer(Employee): raise_amount = 1.10 def __init__(self, first, last, pay, prog_lang): #부모 클래스의 메소드를 실행한다. super().__init__(first, last, pay) #Employee.__init__(first, last, pay) #이 코드도 상위 클래스 __init__ call self.prog_lang = prog_lang dev_1 = Developer('kildong', 'hong', 10000000) # Java와 달리 new keyword를 사용하지 않음. dev_2 = Developer('sunghun', 'kim', 5000000) # emp_1(객체)는 클래스(Employee)의 인스턴스(Instance)이다. #자식클래스가 부모 클래스의 속성과 메소드를 상속하여 정상 동작함. print(dev_1.email) print(dev_2.email) # Employee 를 상속하는 Manager 클래스 class Manager(Employee): #parameter=None은 해당 parameter가 값이 없을 경우 None으로 설정한다.(default value) def __init__(self, first, last, pay, employees=None): #부모 클래스의 메소드를 실행한다. super().__init__(first, last, pay) if employees is None: self.employees = [] else: self.employees = employees #부모 클래스에 없는 메소드 정의 가능 def add_emp(self, emp): if emp not in self.employees: self.employees.append(emp) #list append def remove_emp(self, emp): if emp in self.employees: self.employees.remove(emp) #list remove def print_emps(self): for emp in self.employees: print('-->{}'.format(emp.fullname()))
Instance Type / Subclass 여부 확인
print(isinstance(mgr_1, Manager)) #True print(issubclass(Developer, Employee)) #True print(issubclass(Employee, Manager)) #False
다중상속
- python은 다중상속을 지원하므로 instance 키워드가 없음
class parentA: def print(self): print('parentA') def printA(self): print('parentA print') class parentB: def print(self): print('parentB') def printB(self): print('parentB print') class Child(parentA, parentB): def print(self): super().print() print('child C') ins = Child() ins.print() # 다중 상속 클래스의 선언된 순서에서 우선한 것의 메소드를 실행한다. ins.printB() ins.printA()