์ฝ๋ - ํจ์บ ์์
์ฝ๋ ์ฐธ๊ณ (ํจ์บ ์์
์ ๋ฆฌ)
<์ด์ ๊ธ>
https://silvercoding.tistory.com/28
[python ์ฌํ] 11. ํด๋์ค Getter, Setter, ์ถ์ํด๋์ค , class ABC
์ฝ๋ - ํจ์บ ์์
์ฝ๋ ์ฐธ๊ณ (ํจ์บ ์์
์ ๋ฆฌ) <์ด์ ๊ธ> https://silvercoding.tistory.com/27 https://silvercoding.tistory.com/26 https://silvercoding.tistory.com/25 ์ด๋ฒ ํฌ์คํธ์์๋ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์์..
silvercoding.tistory.com
* ์ด๋ฒ ํฌ์คํ
๋ถํฐ ๊ณต๋ถํ ๊ฒ : 1. ๋ฐ๋ณตํ ๊ฐ์ฒด์ ๋ด๋ถ์ ์ผ๋ก iter ํจ์ ์คํ ๋ด์ฉ, 2. ์ ๋๋ ์ดํฐ ๋์ ์๋ฆฌ, 3. yield from
์ด ์ค์์๋ ์ค๋์ 1~2 ๋ฅผ ํฌ์คํ
ํ๋ค.
- ํ์ด์ฌ ๋ฐ๋ณตํ ์ข
๋ฅ
: for, collections, text file, List, Dict, Set, Tuple, unpacking, *args
---> ๋ฐ๋ณต์ด ๊ฐ๋ฅํ ์ด์ ? -> iter(x) ํจ์๊ฐ ํธ์ถ๋๊ธฐ ๋๋ฌธ
- ๋ฐ๋ณต๋ฌธ ๊ฐ๋จํ ์์
t = 'ABCDEF'
* for ์ฌ์ฉ
for c in t: # ์ํ์คํ์ด๊ธฐ ๋๋ฌธ์ ๋ฐ๋ณต์ด ๊ฐ๋ฅํ๋ค.
print('EX1-1 - ', c)
EX1-1 - A EX1-1 - B EX1-1 - C EX1-1 - D EX1-1 - E EX1-1 - F
* while ์ฌ์ฉ
w = iter(t)
print(type(w))
<class 'str_iterator'>
while True:
try:
print('EX1-2 - ', next(w))
except StopIteration: # ๋ฌธ์๊ฐ ๋์ด์ ์๋๋ฐ ํธ์ถํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋ฏ๋ก
break
EX1-2 - A EX1-2 - B EX1-2 - C EX1-2 - D EX1-2 - E EX1-2 - F
iterator type ์ผ๋ก ๋ณ๊ฒฝํ๊ณ , next ๋ฅผ ํธ์ถํ์ฌ while ๋ฌธ์ผ๋ก ๋ฐ๋ณต์ ์ฌ์ฉํ์๋ค.
from collections import abc
# ๋ฐ๋ณตํ ํ์ธ
print('EX1-3 - ', hasattr(t, '__iter__')) # ---> t๊ฐ __iter__ ์ ์์ฑ์ ๊ฐ๊ณ ์๋ ?
print('EX1-4 - ', isinstance(t, abc.Iterable)) # t๊ฐ abc์ Iterableํด๋์ค์ ๊ฐ์ ์ธ์คํด์ค๋ ? ---> True --> ์ํ๊ฐ ๊ฐ๋ฅํ๋ค.
# dir() ๋ก๋ ํ์ธ ๊ฐ๋ฅ
EX1-3 - True EX1-4 - True
๋ฐ๋ณตํ ํ์
์ธ์ง ์๊ณ ์ถ๋ค๋ฉด ์์ ๊ฐ์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด ๋๋ค. (hasattr(), isinstance(), dir())
- next ๋ฉ์๋ ์ง์ ๊ตฌํ ์์
class WordSplitIter:
def __init__(self, text):
self._idx = 0
self._text = text.split(' ')
def __next__(self):
# print('Called __next__')
try:
word = self._text[self._idx]
except IndexError:
raise StopIteration('stop !')
self._idx += 1
return word
def __iter__(self):
print('Called __iter__')
return self
def __repr__(self):
return 'WordSplit(%s)' % (self._text)
๋ฌธ์ฅ์ ์
๋ ฅํ๋ฉด ๋์ด์ฐ๊ธฐ๋ฅผ ๊ธฐ์ค์ผ๋ก split ํด์ ๋ฆฌ์คํธ์ ๋ฃ์ด์ค _text ๋ฅผ ์์ฑํ๋ค. __next__ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ํ ๋จ์ด์ฉ ๋์ค๋๋ก ๊ตฌํํ๋ค.
* ๊ฐ์ฒด ์์ฑ
wi = WordSplitIter('who says the nights are for sleeping')
* ์ฌ์ฉ
print('EX2-1 - ', wi)
print('EX2-2 - ', next(wi))
print('EX2-3 - ', next(wi))
print('EX2-4 - ', next(wi))
print('EX2-5 - ', next(wi))
print('EX2-6 - ', next(wi))
print('EX2-7 - ', next(wi))
print('EX2-8 - ', next(wi))
# print('EX2-9 - ', next(wi))
EX2-1 - WordSplit(['who', 'says', 'the', 'nights', 'are', 'for', 'sleeping']) EX2-2 - who EX2-3 - says EX2-4 - the EX2-5 - nights EX2-6 - are EX2-7 - for EX2-8 - sleeping
์ฃผ์์ ์ ๊ฑฐํ๊ณ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์๋ฌ๊ฐ ๋๋ค.
Traceback (most recent call last): File "c:/Users/sooki/Desktop/python_high/chapter06_01.py", line 55, in __next__ word = self._text[self._idx] IndexError: list index out of range During handling of the above exception, another exception occurred: Traceback (most recent call last): File "c:/Users/sooki/Desktop/python_high/chapter06_01.py", line 78, in <module> print('EX2-9 - ', next(wi)) File "c:/Users/sooki/Desktop/python_high/chapter06_01.py", line 57, in __next__ raise StopIteration('stop !') StopIteration: stop !
๊ตฌํํด ๋์๋ ์๋ฌ๊ฐ ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ์ด์ ๊ฐ์ด ์๋ฌ๋ฅผ ์ ์ดํ ์ ์๋ค.
- Generator ํจํด
1. ์ง๋ฅํ ๋ฆฌ์คํธ, ๋์
๋๋ฆฌ, ์งํฉ -> ๋ฐ์ดํฐ ์
์ด ์ฆ๊ฐ ํ ๊ฒฝ์ฐ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ์ฉ๋์ด ์ฆ๊ฐ ํ๋ค. -> ์ด ์ ์ ์ ๋๋ ์ดํฐ ๊ฐ ์ํ ํด์ค ์ ์๋ค.
2. ๋จ์ ์คํ์ด ๊ฐ๋ฅํ ์ฝ๋ฃจํด (Coroutine) ๊ตฌํ ์ ์์ฃผ ์ค์ ํ๋ค.
3. ์ ๋๋ ์ดํฐ๋ฅผ ์ด์ฉํ์ฌ ๋์
๋๋ฆฌ , ๋ฆฌ์คํธ๋ฅผ ํ ๋ฒ ํธ์ถ ํ ๋๋ง๋ค ํ๋์ ๊ฐ๋ง ๋ฆฌํด ํ๋ค. <- ๋ฐ๋ผ์ ์์ฃผ ์์ ๋ฉ๋ชจ๋ฆฌ ์์ ํ์ ๋ก ํ๊ฒ ๋๋ค. (๋ชจ๋ ์๋ฃ๊ตฌ์กฐ๋ฅผ ๋ค ์ ์ฅํ๊ณ ์๋ ๊ฒ์ด ์๋๋ผ, next๊ฐ ํธ์ถ๋ ๋ ๊ฐ์ ๋ฐํ ํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ์ฐจ์ง๋์ด ์ ์ ๊ฒ )
class WordSplitGenerator:
def __init__(self, text):
self._text = text.split(' ')
def __iter__(self):
for word in self._text:
yield word # ์ ๋๋ ์ดํฐ
return
def __repr__(self):
return 'WordSplit(%s)' % (self._text)
์์์ ํ๋ WordSplitIter ํด๋์ค์ ๊ฐ์ ๊ธฐ๋ฅ์ ํ๋ฉด์ ์ ๋๋ ์ดํฐ ๋ฅผ ์ด์ฉํ๋ ํด๋์ค๋ฅผ ๊ตฌํํ๋ค. ์ด ๊ฒฝ์ฐ์๋ idx ๋ณ์๋ ํ์๊ฐ ์์ด์ง๋ค. ์ ๋๋ ์ดํฐ ํจํด์ ์ฌ์ฉํ๊ธฐ ์ํ์ฌ yield ๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ค์ํ๋ค. next๊ฐ ํธ์ถ๋๋ฉด์ yield๊ฐ ์คํ๋ ํ ๋ฉ์ถ๋ค. ๋ ๋ค์ next๊ฐ ํธ์ถ๋๋ฉด ๊ธฐ์ตํด ๋์ ๋ถ๋ถ๋ถํฐ ์คํ๋๋๋ก ํด์ค๋ค.
*๊ฐ์ฒด ์์ฑ
wg = WordSplitGenerator('who says the nights are for sleeping')
wt = iter(wg)
๊ฐ์ฒด๋ฅผ ์์ฑํด์ฃผ๊ณ , iter()ํจ์์ ๊ฐ์ฒด๋ฅผ ๋ฃ์ด์ฃผ์ด์ผ ํ๋ค.
print('EX3-1 - ', wt)
EX3-1 - <generator object WordSplitGenerator.__iter__ at 0x00000218C0E87570>
์ด๋ ๊ฒ ๋ฐ๋ณต์ด ๊ฐ๋ฅํ ์ ๋๋ ์ดํฐ ํ์
์ธ ๊ฒ์ ์ ์ ์๋ค.
print('EX3-2 - ', next(wt))
print('EX3-3 - ', next(wt))
print('EX3-4 - ', next(wt))
print('EX3-5 - ', next(wt))
print('EX3-6 - ', next(wt))
print('EX3-7 - ', next(wt))
print('EX3-8 - ', next(wt))
# print('EX3-9 - ', next(wt)) # ์์ธ ์ฒ๋ฆฌ ์๋
EX3-2 - who EX3-3 - says EX3-4 - the EX3-5 - nights EX3-6 - are EX3-7 - for EX3-8 - sleeping
์์์๋ ์์ธ ์ฒ๋ฆฌ๋ฅผ ์ง์ ๊ตฌํํ์๋๋ฐ, ์ด๋ ๊ฒ ์ ๋๋ ์ดํฐ๋ฅผ ํ์ฉํ๋ฉด ์์ธ์ฒ๋ฆฌ๋ ์๋์ผ๋ก ๋๋ค.
- Generator ์์ 1
* Generator : yield ๋ฅผ ๋ง๋๋ฉด ๋ฉ์ถฐ์๋ค๊ฐ next ๋ฅผ ํธ์ถํ๋ฉด ๊ทธ ๋ค์์ ์คํํจ
def generator_ex1():
print('start!')
yield 'AAA'
print('continue')
yield 'BBB'
print('end')
yield ๋ก Generator ๋ฅผ ๊ตฌํํ ํจ์์ด๋ค.
temp = iter(generator_ex1())
print('EX4-1 - ', next(temp))
print('EX4-2 - ', next(temp))
print('EX4-3 - ', next(temp))
start! EX4-1 - AAA continue EX4-2 - BBB end Traceback (most recent call last): File "c:/Users/sooki/Desktop/python_high/chapter06_01.py", line 136, in <module> print('EX4-3 - ', next(temp)) StopIteration
yield ๋ฅผ ๋ง๋๋ฉด ๋ฉ์ถ์ด ์๋ค๊ฐ next ๊ฐ ํธ์ถ๋๋ฉด ์คํ๋๋ ํํ์ด๋ค. 4-3 ์ฒ๋ผ next ๋ฅผ ๋ ํ๋ฉด yield ๊ฐ ๋์ด์ ์๊ธฐ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋๋ค.
* for, while๊ณผ ๊ฐ์ ๋ฐ๋ณต๋ฌธ์์ ์ฌ์ฉ์ด ์ ์ ํจ
for v in generator_ex1():
print('EX4-3 - ', v) # next๋ฅผ ๋ด๋ถ์ ์ผ๋ก ํธ์ถ, StopIteration์๋ฌ๋ ๋ด๋ถ์ ์ผ๋ก ์ก์์ค
start! EX4-3 - AAA continue EX4-3 - BBB end
for๋ฌธ์ ์ด์ฉํ์ฌ ์ ๋๋ ์ดํฐ๋ฅผ ์คํํ๋ฉด next๊ฐ ๋ด๋ถ์ ์ผ๋ก ํธ์ถ๋๋ฉฐ, ์๋ฌ๋ ๋ด๋ถ์ ์ผ๋ก ์ก์์ง๋ฏ๋ก ์งง์ ์ฝ๋๋ก ๊น๋ํ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
- Generator ์์ 2
temp2 = [x * 3 for x in generator_ex1()]
temp3 = (x * 3 for x in generator_ex1())
์ง๋ฅํ ๋ฆฌ์คํธ์ ํํ์ ์์ฑํ๋ค. ์ด ๊ฒฝ์ฐ์ ํํ์ ์ ๋๋ ์ดํฐ ๊ฐ ๋๋ค.
print('EX5-1 - ', temp2) # ์ด๋ฏธ ๋ฉ๋ชจ๋ฆฌ์ ๋ง๋ค์ด์ ์ฌ๋ฆฐ ๊ฒ
print('EX5-2 - ', temp3) # ์ ๋๋ ์ดํฐ ์์ฑ. ์์ง ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ผ๊ฐ ์์ง ์์. next๊ฐ ํธ์ถ๋์ด์ผ๋ง ๋ง๋ค์ด์ง
EX5-1 - ['AAAAAAAAA', 'BBBBBBBBB'] EX5-2 - <generator object <genexpr> at 0x000001B3528D66D8>
5-1 ์ list comprehension ์ ๋ฉ๋ชจ๋ฆฌ์ ์ด๋ฏธ ํ ๋น๋์ด ์ฌ๋ผ๊ฐ ์๋ ๊ฒ์ ๋ฐํํ ๊ฒ์ด๊ณ , ์ ๋๋ ์ดํฐ ์ธ 5-2 ๋ ์์ง ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ผ๊ฐ ์๋ ๊ฒ์ด ์๋๊ณ , next ๊ฐ ํธ์ถ๋ ๋ ๋ง๋ค์ด์ง๋ค. (๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ ์ ์ด์ )
for i in temp2:
print('EX5-3 - ', i)
EX5-3 - AAAAAAAAA EX5-3 - BBBBBBBBB
๋ฆฌ์คํธ ํ์ด๋ฏ๋ก for๋ฌธ์ผ๋ก ๋ฐ๋ณตํ ์ ์๋ค.
for i in temp3: # ๋น
๋ฐ์ดํฐ๋ฅผ ์ด์ฉํ ๋๋ ์ ๋๋ ์ดํฐ๋ก ๋ฐ๋ณต๋ฌธ ๋๋ฆฌ๋ ๊ฒ์ ๊ถ์ฅ
print('EX5-4 - ', i)
start! EX5-4 - AAAAAAAAA continue EX5-4 - BBBBBBBBB end
๊ฒฐ๊ณผ๋ ๋น์ทํด๋ณด์ด์ง๋ง ๊ณผ์ ๊ณผ ๋ฉ๋ชจ๋ฆฌ ์ฐจ์ง๋์ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ ํฉํ ๋ฐฉ๋ฒ์ ์ฐ๋๋ก ํ์!
- Generator ์์ 3 (์์ฃผ ์ฌ์ฉํ๋ ํจ์)
Generator ์์ 3 ์์๋ itertools ๋ฅผ ์ด์ฉํ Generator ์ฌ์ฉ์ ํด๋ณธ๋ค!
import itertools
์ฐ์ itertools ๋ฅผ import ํ๋ค.
* ๋ฌดํ (๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋์ง ์๋ ๋ค๋ ๊ฒ ! ) - itertools.count
gen1 = itertools.count(1, 2.5)
itertools.count(๊ธฐ๋ณธ๊ฐ, ์ฆ๊ฐ๊ฐ) ์ ์์ฑํ๋ค.
print('EX6-1 - ', next(gen1))
print('EX6-2 - ', next(gen1))
print('EX6-3 - ', next(gen1))
print('EX6-4 - ', next(gen1))
EX6-1 - 1 EX6-2 - 3.5 EX6-3 - 6.0 EX6-4 - 8.5
์์ ๊ฐ์ด 1 ๋ถํฐ ์์ํ์ฌ next ๋ฅผ ํธ์ถํ๋ฉด 2.5 ์ฉ ์ฆ๊ฐ์ํฌ ์ ์๋ค. ๋ฌดํ์ผ๋ก ์ฆ๊ฐ์ํฌ ์ ์์ผ๋ฉฐ, ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋์ง ์๊ณ next ๊ฐ ํธ์ถ๋๊ธฐ ์ ๊น์ง๋ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋์ด ์์ง ์๋ค.
# for v in gen1:
# print(v)
for๋ฌธ์ผ๋ก ์ถ๋ ฅํ๋ฉด ๋ฌดํ์ผ๋ก 2.5์ฉ ์ฆ๊ฐํ๊ฒ ๋๋ค.
* ์กฐ๊ฑด - itertools.takewhile
gen2 = itertools.takewhile(lambda n: n < 10, itertools.count(1, 2.5))
์กฐ๊ฑด์ ๊ฑธ ์ ์๋ ํจ์์ด๋ค. ์ด ๊ฒฝ์ฐ์๋ ๊ฐ์ด 10 ์ดํ์ผ ๋๋ง 2.5์ฉ ์ฆ๊ฐ์ํจ๋ค.
for v in gen2:
print('EX6-5 - ', v)
EX6-5 - 1 EX6-5 - 3.5 EX6-5 - 6.0 EX6-5 - 8.5
* ํํฐ ๋ฐ๋ - itertools.filterfalse
gen3 = itertools.filterfalse(lambda n: n < 3, [1, 2, 3, 4, 5])
filterfalseํจ์๋ ์กฐ๊ฑด์ ๊ฑธ์ด๋๊ณ ์กฐ๊ฑด๊ณผ ๋ฐ๋๋๋ ๊ฐ์ ๋ฐํํ๋๋ก ํ๋ค.
for v in gen3:
print('EX6-6 - ', v)
EX6-6 - 3 EX6-6 - 4 EX6-6 - 5
3๋ฏธ๋ง์ธ ์๋ก ์กฐ๊ฑด์ ๊ฑธ์ด๋์์ผ๋ฏ๋ก ๋ฐ๋๋๋ 3, 4, 5 ๊ฐ ์ถ๋ ฅ๋์๋ค.
* ๋์ ํฉ๊ณ - itertools.accumulate
gen4 = itertools.accumulate([x for x in range(1, 11)])
accumulate๋ ๋์ ํด์ ๋ํด์ฃผ๋ ํจ์์ด๋ค.
for v in gen4:
print('EX6-7 - ', v)
EX6-7 - 1 EX6-7 - 3 EX6-7 - 6 EX6-7 - 10 EX6-7 - 15 EX6-7 - 21 EX6-7 - 28 EX6-7 - 36 EX6-7 - 45 EX6-7 - 55
1๋ถํฐ 10๊น์ง ๋์ ์ผ๋ก ๋ํด์ก๋ค.
* ์ฐ๊ฒฐ1 - itertools.chain
gen5 = itertools.chain('ABCDE', range(1, 11, 2))
chain ์ ์ธ์๊ฐ๋ค์ ์ฐ๊ฒฐํด์ค๋ค.
print('EX5-8 - ', list(gen5))
EX5-8 - ['A', 'B', 'C', 'D', 'E', 1, 3, 5, 7, 9]
* ์ฐ๊ฒฐ2 - itertools.chain
gen6 = itertools.chain(enumerate('ABCDE'))
enumerate ๋ฅผ ์ด์ฉํ์ฌ ์ธ๋ฑ์ค์ ๋ฌถ์ด์ค ์๋ ์๋ค.
print('EX6-9 - ', list(gen6))
EX6-9 - [(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D'), (4, 'E')]
ํํ ๋ก ๋ฌถ์ธ ๊ฒ์ ๋ณผ ์ ์๋ค.
* ๊ฐ๋ณ - itertools.product
gen7 = itertools.product('ABCDE')
๊ฐ๋ณ์ ํํ ์์ ๋ฃ์ด์ค ์๋ ์๋ค.
print('EX6-10 - ', list(gen7))
EX6-10 - [('A',), ('B',), ('C',), ('D',), ('E',)]
* ์ฐ์ฐ - itertools.product
gen8 = itertools.product('ABCDE', repeat=2) # ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ๋ฌถ์ด์ค๋ค.
repeat=2๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋ชจ๋ ๊ฐ๋ฅํ ๊ฒฝ์ฐ์ ์๋ก 2๊ฐ์ฉ ๋ฌถ์ด์ค๋ค.
print('EX6-11 - ', list(gen8))
EX6-11 - [('A', 'A'), ('A', 'B'), ('A', 'C'), ('A', 'D'), ('A', 'E'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'A'), ('C', 'B'), ('C', 'C'), ('C', 'D'), ('C', 'E'), ('D', 'A'), ('D', 'B'), ('D', 'C'), ('D', 'D'), ('D', 'E'), ('E', 'A'), ('E', 'B'), ('E', 'C'), ('E', 'D'), ('E', 'E')]
* ๊ทธ๋ฃนํ - itertools.groupby
gen9 = itertools.groupby('AAABBCCCCDDEEE')
groupbyํจ์๋ ๊ฐ์ ์ข
๋ฅ๋ผ๋ฆฌ ๋ฌถ์ด์ค๋ค.
# print('EX6-12 - ', list(gen9))
EX6-12 - [('A', <itertools._grouper object at 0x000001F2EE3E40B8>), ('B', <itertools._grouper object at 0x000001F2EE3E4160>), ('C', <itertools._grouper object at 0x000001F2EE3E4198>), ('D', <itertools._grouper object at 0x000001F2EE3E41D0>), ('E', <itertools._grouper object at 0x000001F2EE3E4208>)]
for chr, group in gen9:
print('EX6-12 - ', chr, ' : ', list(group))
EX6-12 - A : ['A', 'A', 'A'] EX6-12 - B : ['B', 'B'] EX6-12 - C : ['C', 'C', 'C', 'C'] EX6-12 - D : ['D', 'D'] EX6-12 - E : ['E', 'E', 'E']
for๋ฌธ์ผ๋ก ๋๋ ค์ฃผ๊ณ , group์ list์ ๋ฃ์ด ๊ทธ๋ฃน๋ณ๋ก ํ์ธํด๋ณผ ์ ์๋ค.