1. 학습목표
2. 학습내용
# 객체 슬라이싱c
class ObjectS():
def __init__(self):
self._numbers = [n for n in range(1, 10, 3)]
def __len__(self):
return len(self._numbers)
def __getitem__(self, idx):
return self._numbers[idx]
s = ObjectS()
# print('EX3-1 -', s.__dict__)
# EX3-1 - {'_numbers': [1, 4, 7]}
# print('EX3-2 -', len(s))
# EX3-2 - 3
# print('EX3-4 -', s[1:2])
# EX3-4 - [4]
# 파이선 추상클래스
# 참고 : https://docs.python.org/3/library/collections.abc.html
# 추상클래스는 자체적으로 객체 생성 불가!
# 추상클래스는 상속을 통해서 자식 클래스에서 인스턴스를 생성해야 함
# 추상클래스를 사용하는 이유:
# 개발과 관련된 공통된 내용(필드, 메소드) 추출 및 통합해서 공통된 내용으로 작성하게 하는 것
# 반드시 상속받아야하는 속성을 강제한는 것?!
# sequence 삭송 받지 않았지만, 자동으로 __iter__, __contain__ 기능 작동하도록 함!
# 객체 전체를 자동으로 조사 -> 시퀀스 프로토콜
class IterTestA():
def __getitem__(self, idx):
return range(1, 50, 2)[idx]
i1 = IterTestA()
# print('EX4-1 -', i1[4])
# EX4-1 - 9
# print('EX4-2 -',i1[4:10])
# EX4-2 - range(9, 21, 2)
# print('EX4-2 -',3 in i1[1:10])
# EX4-2 - True
## iterator를 구현하지 않았지만 파이썬이 똑똑하게 작동하도록 함
# print('EX4-3 -', [i for i in i1])
# EX4-3 - [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49]
# Sequence 상속
# 요구사항인 추상메소드를 모두 구현해야 동작
# FM으로 구현했을 때는, 반드시 추상메소드를 모두 구현해야 동작하는 지 테스트!!
# 결론은 "추상"메소드를 상속받으면! 반드시 오버랑이딩 해줘야함!
from collections.abc import Sequence
class IterTestB(Sequence):
def __getitem__(self, idx):
return range(1, 50, 2)[idx]
# i2 = IterTestB()
"""
Traceback (most recent call last):
File "/Users/marie/PycharmProjects/untitled1/fc_lecture.py", line 63, in <module>
i2 = IterTestB()
TypeError: Can't instantiate abstract class IterTestB with abstract methods __len__
"""
class IterTestC(Sequence):
def __getitem__(self, idx):
print('__getitem__,', idx)
return range(1, 50, 2)[idx]
def __len__(self, idx):
print('__len__', idx)
return len(range(1, 50, 2)[idx])
i3 = IterTestC()
# print('EX5-1 -', i3[4])
"""
__getitem__, 4
EX5-1 - 9
"""
# print('EX5-1 -', i3[4:10])
"""
__getitem__, slice(4, 10, None)
EX5-1 - range(9, 21, 2)
"""
# print('EX5-1 -', 3 in i3[1:10])
"""
__getitem__, slice(1, 10, None)
EX5-1 - True
"""
## abc 활용 예제
import abc
class RandomMachine(abc.ABC): # metaClass = abc.ABCMeta (3.4 이하)
# __metaclass__ = abc.ABCMEta
# 추상 메소드
# 추상메소드는 메소드 위에 데코레이터료 표시함!
# 추상 메소드는 자식에서 반드시 구현되어야 함(강제성!)
# 추상 메소드가 아닌 것은 자식에서 반드시 구현되지 않아도 됨!
## 추상클래스에서 이렇게 데코레이터로 annotation된 메소드는 상속받은 자식에서 반드시 구현되어야함!!(강제!)
@abc.abstractmethod
def load(self, iterobj):
'''Iterable 항목 추가'''
# 추상 메소드
@abc.abstractmethod
def pick(self, iterobj):
'''무작위 항목 뽑기'''
def inspect(self):
items = []
while True:
try:
items.append(self.pick())
except LookupError:
break
return tuple(sorted(items))
import random
class CraneMachine(RandomMachine):
def __init__(self, items):
self._randomizer = random.SystemRandom()
self._items = []
self.load(items)
def load(self, items):
self._items.extend(items)
self._randomizer.shuffle(self._items)
def pick(self):
try:
return self._items.pop()
except IndexError:
raise LookupError('Empty Crane Box')
def __call__(self):
return self.pick()
# 서브 클래스 확인
# print('EX5-1 -', issubclass(RandomMachine, CraneMachine))
# EX5-1 - False
# print('EX5-2 -', issubclass(CraneMachine, RandomMachine))
# EX5-2 - True
# 상속 구조 확인
# print('EX5-3 -', CraneMachine.__mro__)
"""
EX5-3 -
(<class '__main__.CraneMachine'>,
<class '__main__.RandomMachine'>,
<class 'abc.ABC'>,
<class 'object'>)
"""
cm = CraneMachine(range(1, 100))
# print('EX5-4 -', cm._items)
# EX5-4 - [3, 73, 74, 99, 1, 71, 46, 24, 13, 80, 54, 62, 47, 10, 64, 31, 69, 81, 51, 70, 9, 72, 45, 4, 16, 30, 33, 17, 28, 79, 7, 55, 89, 84, 27, 22, 19, 66, 23, 41, 39, 90, 14, 11, 68, 85, 8, 37, 2, 32, 98, 43, 76, 92, 95, 59, 5, 48, 65, 67, 82, 91, 77, 97, 15, 83, 18, 58, 87, 78, 93, 57, 34, 29, 52, 40, 12, 36, 25, 56, 61, 26, 88, 75, 60, 6, 63, 94, 49, 21, 38, 96, 86, 50, 44, 42, 35, 53, 20]
# print('EX5-5 -', cm.pick())
# EX5-5 - 10
# callable 메소드 확인
# print('EX5-6 -', cm)
# EX5-6 - <__main__.CraneMachine object at 0x102e4eb00>
# inspect 메소드는 부모 클래서에서 일반메소드임 (추상메소드 아님)
# print('EX5-7 -', cm.inspect())
# EX5-7 - (28,)
3. 느낀 점