์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ)

 

 

<์ด์ „ ๊ธ€>

https://silvercoding.tistory.com/31

 

[python ์‹ฌํ™”] 14. Future ๋™์‹œ์„ฑ/ ๋น„๋™๊ธฐ ์ž‘์—… ์‹คํ–‰/ ThreadPoolExecutor, ProcessPoolExecutor

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ) <์ด์ „ ๊ธ€> https://silvercoding.tistory.com/30 https://silvercoding.tistory.com/29 https://silvercoding.tistory.com/28 https://silvercoding.tistory.com/27..

silvercoding.tistory.com

 

 

< Asyncio ์ฐธ๊ณ ๋ฌธ์„œ >

https://docs.python.org/ko/3/library/asyncio.html

 

asyncio — ๋น„๋™๊ธฐ I/O — Python 3.9.6 ๋ฌธ์„œ

 

docs.python.org

 

- Asyncio 

: ๋น„๋™๊ธฐ I/O Coroutine ์ž‘์—… ( *๋™๊ธฐ: ๊ธฐ๋‹ค๋ ค์•ผ ํ•˜๋Š” ๊ฒƒ , ๋น„๋™๊ธฐ: ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์‹คํ–‰๋˜๋Š” ๊ฒƒ) 

: Generator : ๋ฐ˜๋ณต์ ์ธ ๊ฐ์ฒด Return (yield) , ์ฆ‰, ์‹คํ–‰ํ•˜๊ณ  stop -> ๋‹ค๋ฅธ ์ž‘์—…์œผ๋กœ์˜ ์œ„์ž„ -> stop ์ง€์ ๋ถ€ํ„ฐ ์žฌ ์‹คํ–‰ํ•˜๋Š” ์›๋ฆฌ์ด๋‹ค. 

: Non-Blocking ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์— ์ ํ•ฉํ•˜๋‹ค. 

 

 

* ๋ณธ ํฌ์ŠคํŒ…์—์„œ ์‹ค์Šตํ•  ๋ฐฉ๋ฒ•๋“ค 

1. ์ˆœ์ฐจ์‹คํ–‰ 

2. ์“ฐ๋ ˆ๋“œ๋งŒ ์‚ฌ์šฉ 

3. ์ฝ”๋ฃจํ‹ด์—์„œ ์“ฐ๋ ˆ๋“œ ์šฐํšŒ ์‚ฌ์šฉ 

 

 

 

- 1. BlockIO ์˜ˆ์ œ  : ์ˆœ์ฐจ์‹คํ–‰ 

import timeit
from urllib.request import urlopen

ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ import ํ•˜๊ธฐ 

 

urls = ['http://daum.net', 'https://google.com', 'https://apple.com', 'https://tistory.com', 'https://github.com', 'https://naver.com']

์˜ˆ์ œ์—์„œ url์„ openํ•ด ๋ณด๋Š” ์‹ค์Šต์„ ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— url ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค. ์ด 6 ๊ฐœ์˜ url์„ ๋„ฃ์–ด ์ฃผ์—ˆ๋‹ค. 

 

start = timeit.default_timer()

์ˆœ์ฐจ ์‹คํ–‰์„ ํ•˜๊ธฐ ์ „ ์‹œ๊ฐ„์„ ๊ธฐ๋กํ•ด ๋‘”๋‹ค. ์ด๋ฒˆ์—๋Š” timeit.default_timer()๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹œ๊ฐ„์„ ์ธก์ •ํ•œ๋‹ค. 

 

 

* ์ˆœ์ฐจ ์‹คํ–‰๋ถ€ 

for url in urls:
    print('Start', url)
    # ์‹ค์ œ ์š”์ฒญ 
    text = urlopen(url)
    # ์‹ค์ œ ๋‚ด์šฉ
    # print('Contents', text.read())
    print('Done', url)

์œ„์™€ ๊ฐ™์ด urlopen์„ ์‚ฌ์šฉํ•˜์—ฌ url์— ์‹ค์ œ ์š”์ฒญ์„ ํ•œ๋‹ค. 

 

 

* ์‹œ๊ฐ„ ์ธก์ • : ์™„๋ฃŒ์‹œ๊ฐ„ - ์‹œ์ž‘์‹œ๊ฐ„ / ๊ฒฐ๊ณผ ์ถœ๋ ฅ

duration = timeit.default_timer() - start

# ์ด ์‹คํ–‰์‹œ๊ฐ„ 
print('Total Time', duration)

 Start http://daum.net 
 Done http://daum.net 
 Start https://google.com 
 Done https://google.com 
 Start https://apple.com 
 Done https://apple.com 
 Start https://tistory.com 
 Done https://tistory.com 
 Start https://github.com 
 Done https://github.com 
 Start https://naver.com 
 Done https://naver.com 
 Total Time 12.8696096 

์ˆœ์ฐจ์ ์œผ๋กœ url๋ฆฌ์ŠคํŠธ์— ์ ์—ˆ๋˜ ์ˆœ์„œ๋Œ€๋กœ url์š”์ฒญ์ด ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์‹œ๊ฐ„์€ ์ด 13์ดˆ ์ •๋„๊ฐ€ ๊ฑธ๋ ธ๋‹ค. 

 

 

 

 

 

 

 

 

 

 

*** BlockIO : Thread ์‚ฌ์šฉ 

: ์“ฐ๋ ˆ๋“œ ๊ฐœ์ˆ˜ ๋ฐ GIL ๋ฌธ์ œ ์—ผ๋‘, ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ ํ•ด๊ฒฐ (๋ฎคํ…์Šค)

 

 

- 2. Thread๋งŒ ์‚ฌ์šฉ 

 

* ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ import 

import timeit
from urllib.request import urlopen
from concurrent.futures import ThreadPoolExecutor
import threading

 

* url ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ ๋ฐ ์‹œ๊ฐ„ ๊ธฐ๋ก 

urls = ['http://daum.net', 'https://google.com', 'https://apple.com', 'https://tistory.com', 'https://github.com', 'https://naver.com']
start = timeit.default_timer()

 

 

* fetch ํ•จ์ˆ˜ ์„ ์–ธ

def fetch(url):
    print('Thread Name : ', threading.current_thread().getName(), 'Start', url)  # ํ˜„์žฌ ์“ฐ๋ž˜๋“œ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์คŒ
    urlopen(url)
    print('Thread Name : ', threading.current_thread().getName(), 'Done', url)

ํ˜„์žฌ ์“ฐ๋ ˆ๋“œ์˜ ์ด๋ฆ„๊ณผ , ์‹œ์ž‘(start) ๊ณผ ์™„๋ฃŒ(Done)์˜ ๊ณผ์ •์„ ์ถœ๋ ฅํ•˜๋„๋ก ํ•˜๋Š” fetch ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. 

 

 

* main ํ•จ์ˆ˜ ์„ ์–ธ - fetchํ•จ์ˆ˜ ์‚ฌ์šฉ 

def main():
    with ThreadPoolExecutor(max_workers=10) as executor: 
        for url in urls:
            executor.submit(fetch, url)

ThreadPoolExecutor๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , max_workers๋Š” 10์œผ๋กœ ๋ฐ›์•„์ค€๋‹ค. ์ด์ œ for๋ฌธ์„ ์ด์šฉํ•˜์—ฌ url์„ ํ•œ๊ฐœ์”ฉ ๋„ฃ์–ด์„œ submit์œผ๋กœ fetchํ•จ์ˆ˜์— ์ ์šฉํ•ด ์ค€๋‹ค. 

 

 

 

* ์‹คํ–‰ 

if __name__ == '__main__':
    # ํ•จ์ˆ˜ ์‹คํ–‰ 
    main()
    
    # ์™„๋ฃŒ์‹œ๊ฐ„ - ์‹œ์ž‘์‹œ๊ฐ„
    duration = timeit.default_timer() - start

    # ์ด ์‹คํ–‰์‹œ๊ฐ„   
    print('Total Time', duration)

 Thread Name :  ThreadPoolExecutor-0_0 Start http://daum.net 
 Thread Name :  ThreadPoolExecutor-0_1 Start https://google.com 
 Thread Name :  ThreadPoolExecutor-0_2 Start https://apple.com 
 Thread Name :  ThreadPoolExecutor-0_3 Start https://tistory.com 
 Thread Name :  ThreadPoolExecutor-0_4 Start https://github.com 
 Thread Name :  ThreadPoolExecutor-0_5 Start https://naver.com 
 Thread Name :  ThreadPoolExecutor-0_4 Done https://github.com 
 Thread Name :  ThreadPoolExecutor-0_2 Done https://apple.com 
 Thread Name :  ThreadPoolExecutor-0_5 Done https://naver.com 
 Thread Name :  ThreadPoolExecutor-0_3 Done https://tistory.com 
 Thread Name :  ThreadPoolExecutor-0_0 Done http://daum.net 
 Thread Name :  ThreadPoolExecutor-0_1 Done https://google.com 
 Total Time 0.9581279
 

start๋Š” for๋ฌธ์— ๋“ค์–ด๊ฐ„ ์ˆœ์„œ๋Œ€๋กœ ์ถœ๋ ฅ์ด ๋˜์—ˆ๋Š”๋ฐ, Done์€ ์ˆœ์„œ๊ฐ€ ์ผ์ •ํ•˜์ง€ ์•Š์€ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. submit ํ•จ์ˆ˜๋Š” ๋จผ์ € ์ผ์ด ๋๋‚˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ์˜ค๋Š” ๊ฒƒ์ผ ๋ฟ, ์ˆœ์„œ์— ๋Œ€ํ•œ ์‹ ๊ฒฝ์„ ์“ฐ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.  ์‹œ๊ฐ„์€ 1์ดˆ๋„ ๋˜์ง€ ์•Š๋Š”๋‹ค! ๊ต‰์žฅํžˆ ์ค„์–ด ๋“  ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

 

 

 

 

- 3. ์ฝ”๋ฃจํ‹ด์—์„œ ์“ฐ๋ ˆ๋“œ ์šฐํšŒ ์‚ฌ์šฉ 

 

<์ฐธ๊ณ >

https://docs.python.org/ko/3/library/asyncio-task.html

 

์ฝ”๋ฃจํ‹ด๊ณผ ํƒœ์Šคํฌ — Python 3.9.6 ๋ฌธ์„œ

์ฝ”๋ฃจํ‹ด๊ณผ ํƒœ์Šคํฌ ์ด ์ ˆ์—์„œ๋Š” ์ฝ”๋ฃจํ‹ด๊ณผ ํƒœ์Šคํฌ๋กœ ์ž‘์—…ํ•˜๊ธฐ ์œ„ํ•œ ๊ณ ๊ธ‰ asyncio API์— ๊ด€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. async/await ๋ฌธ๋ฒ•์œผ๋กœ ์„ ์–ธ๋œ ์ฝ”๋ฃจํ‹ด์€ asyncio ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ

docs.python.org

*** ์ฝ”๋ฃจํ‹ด์€ ๋‹จ์ผ ์“ฐ๋ ˆ๋“œ๋ผ๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ด๋‹ค. ํ•จ์ˆ˜ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋“ฏ ๋ณด์ด๊ฒŒ ํ•ด์ค€๋‹ค. ๋‹จ์ผ ์“ฐ๋ ˆ๋“œ์—์„œ ์ตœ์ ์˜ ์„ฑ๋Šฅ์„ ์ด๋Œ์–ด๋‚ด๊ธฐ ์œ„ํ•ด ์ œ์–ด๋ฅผ ์–‘๋ณดํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉฐ, ๋น ๋ฅด๊ฒŒ ๋™์‹œ์„ฑ ๊ธฐ๋ฒ•์„ ํ™œ์šฉํ•˜๋Š” ํŒจํ„ด์ด๋‹ค. 

 

* ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ import 

# aiohttp ์‚ฌ์šฉ ๊ฐ€๋Šฅ (Asyncio ์ง€์›)
from concurrent import futures
import timeit
from urllib.request import urlopen
from concurrent.futures import ThreadPoolExecutor
import threading
import asyncio

 

* url ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ ๋ฐ ์‹œ๊ฐ„ ๊ธฐ๋ก 

urls = ['http://daum.net', 'https://google.com', 'https://apple.com', 'https://tistory.com', 'https://github.com', 'https://naver.com']
start = timeit.default_timer()

 

 

 

* fetch ํ•จ์ˆ˜ ์„ ์–ธ 

async def fetch(url, executor):
    print('Thread Name : ', threading.current_thread().getName(), 'Start', url)  # ํ˜„์žฌ ์“ฐ๋ž˜๋“œ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์คŒ
    res = await loop.run_in_executor(executor, urlopen, url) # (์ผ๊พผ, ์ผ๊พผ์ด ์ฒ˜๋ฆฌํ•  ํ•จ์ˆ˜, ํ•ด์•ผ๋  ์ผ (์‚ฌ์ดํŠธ)) / loop ์•ˆ์—๋Š” futures๊ฐ€ ๋“ค์–ด๊ฐ€ ์žˆ์Œ . 
    print('Thread Name : ', threading.current_thread().getName(), 'Done', url)
    return res.read()[0:5]

https://silvercoding.tistory.com/30

 

[python ์‹ฌํ™”] 13. ์ฝ”๋ฃจํ‹ด (coroutine) , yield from

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ) <์ด์ „ ๊ธ€> https://silvercoding.tistory.com/29 https://silvercoding.tistory.com/28 https://silvercoding.tistory.com/27 https://silvercoding.tistory.com/26..

silvercoding.tistory.com

์œ„์˜ ํฌ์ŠคํŒ…์—์„œ yield from์„ ๊ณต๋ถ€ํ•˜์˜€๋‹ค. ๋ฒ„์ „ 3.7? ์ด์ƒ ๋ถ€ํ„ฐ await ์œผ๋กœ ๋ฐ”๋€Œ์—ˆ๊ณ  , ๋ณธ ํฌ์ŠคํŒ…์—์„œ๋Š” await์„ ์‚ฌ์šฉํ•œ๋‹ค. 

 

<loop ์ฐธ๊ณ  ๋ฌธ์„œ>

https://docs.python.org/ko/3/library/asyncio-eventloop.html

 

์ด๋ฒคํŠธ ๋ฃจํ”„ — Python 3.9.6 ๋ฌธ์„œ

์ด๋ฒคํŠธ ๋ฃจํ”„ ์†Œ์Šค ์ฝ”๋“œ: Lib/asyncio/events.py, Lib/asyncio/base_events.py ๋จธ๋ฆฌ๋ง ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋ชจ๋“  asyncio ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋น„๋™๊ธฐ ํƒœ์Šคํฌ ๋ฐ ์ฝœ๋ฐฑ์„ ์‹คํ–‰ํ•˜๊ณ  ๋„คํŠธ์›Œํฌ IO ์—ฐ์‚ฐ

docs.python.org

 

 

* main ํ•จ์ˆ˜ ์„ ์–ธ 

async def main():
    # ์“ฐ๋ ˆ๋“œ ํ’€ ์ƒ์„ฑ 
    executor = ThreadPoolExecutor(max_workers=10)
    # asyncio.ensure_future 
    futures = [asyncio.ensure_future(fetch(url, executor)) for url in urls]
    # await = yield from 
    rst = await asyncio.gather(*futures)  # unpacking

    print()
    print('Result : ', rst)

์ง€๋Šฅํ˜• ๋ฆฌ์ŠคํŠธ์ธ futures๋ฅผ ์„ ์–ธํ•œ๋‹ค. asyncio.ensure_future์— fetchํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•œ๋‹ค. 

 

 

 

* ๊ฒฐ๊ณผ ์‹คํ–‰ 

if __name__ == '__main__':
    # ๋ฃจํ”„ ์ƒ์„ฑ 
    loop = asyncio.get_event_loop()
    # ๋ฃจํ”„ ๋Œ€๊ธฐ 
    loop.run_until_complete(main())
    # ํ•จ์ˆ˜ ์‹คํ–‰ 
    main()   

    # ์™„๋ฃŒ์‹œ๊ฐ„ - ์‹œ์ž‘์‹œ๊ฐ„
    duration = timeit.default_timer() - start

    # ์ด ์‹คํ–‰์‹œ๊ฐ„   
    print('Total Time', duration)

 Thread Name :  MainThread Start http://daum.net 
 Thread Name :  MainThread Start https://google.com 
 Thread Name :  MainThread Start https://apple.com 
 Thread Name :  MainThread Start https://tistory.com 
 Thread Name :  MainThread Start https://github.com 
 Thread Name :  MainThread Start https://naver.com 
 Thread Name :  MainThread Done https://github.com 
 Thread Name :  MainThread Done https://apple.com 
 Thread Name :  MainThread Done https://naver.com 
 Thread Name :  MainThread Done https://tistory.com 
 Thread Name :  MainThread Done http://daum.net 
 Thread Name :  MainThread Done https://google.com 

 Result :  [b'<!DOC', b'<!doc', b'\n\t\n\n\n', b'\n\t<!d', b'\n\n\n\n\n', b'\n<!do'] 
 c:/Users/./Desktop/python_high/chapter06_04_03.py:57: RuntimeWarning: coroutine 'main' was never awaited 
  main() 
 RuntimeWarning: Enable tracemalloc to get the object allocation traceback       
 Total Time 1.3151724 

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ˆœ์„œ์— ์ƒ๊ด€ ์—†์ด ์ผ์„ ํ•˜๋ฉฐ, ์‹œ๊ฐ„์€ 2๋ฒˆ๋ฐฉ๋ฒ•๋ณด๋‹ค๋Š” ์˜ค๋ž˜ ๊ฑธ๋ฆฌ์ง€๋งŒ ๊ทธ๋ž˜๋„ 1.3์ดˆ๋กœ ๋น ๋ฅด๊ฒŒ ์‹คํ–‰๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ)

 

 

<์ด์ „ ๊ธ€>

https://silvercoding.tistory.com/30

 

[python ์‹ฌํ™”] 13. ์ฝ”๋ฃจํ‹ด (coroutine) , yield from

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ) <์ด์ „ ๊ธ€> https://silvercoding.tistory.com/29 https://silvercoding.tistory.com/28 https://silvercoding.tistory.com/27 https://silvercoding.tistory.com/26..

silvercoding.tistory.com

 

* Future ๋™์‹œ์„ฑ / ๋น„๋™๊ธฐ ์ž‘์—… ์‹คํ–‰ 

์ง€์—ฐ์‹œ๊ฐ„ (Block) CPU ๋ฐ ๋ฆฌ์†Œ์Šค ๋‚ญ๋น„ ๋ฐฉ์ง€ -> (FILE) Network I/O๊ด€๋ จ ์ž‘์—… ๋™์‹œ์„ฑ ํ™œ์šฉ ๊ถŒ์žฅ 

: ์ ํ•ฉํ•œ ์ž‘์—…์ผ ๊ฒฝ์šฐ ์ˆœ์ฐจ ์ง„ํ–‰๋ณด๋‹ค ์••๋„์ ์œผ๋กœ ์„ฑ๋Šฅ ํ–ฅ์ƒ 

 

 

 

* ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ ์‹ค์Šตํ•  3๊ฐ€์ง€ 

1. ์ˆœ์ฐจ ์‹คํ–‰ 

2. concurrent.futures ๋ฐฉ๋ฒ•1 

3. concurrent.futures ๋ฐฉ๋ฒ• 2 

 

import os 
import time # ์„ฑ๋Šฅ์ธก์ • 
import sys
import csv
# ๊ตญ๊ฐ€ ์ •๋ณด 
NATION_LS = ('Singapore Germany Israel Norway Italy Canada France Spain Maxico').split()
# ์ดˆ๊ธฐ CSV ์œ„์น˜ 
TARGET_CSV = './resources/nations.csv'
# ์ €์žฅ ํด๋” ์œ„์น˜ 
DEST_DIR = './csvs'
# CSV ํ—ค๋” ๊ธฐ์ดˆ ์ •๋ณด 
HEADER = ['Region','Country','Item Type','Sales Channel','Order Priority','Order Date','Order ID','Ship Date','Units Sold','Unit Price','Unit Cost','Total Revenue','Total Cost','Total Profit']

<csv ํŒŒ์ผ : ํŒจ์ŠคํŠธ ์บ ํผ์Šค ์ œ๊ณต>

NATION_LS : ์‚ฌ์šฉํ•  ๊ตญ๊ฐ€ ์ด๋ฆ„ ๋ฆฌ์ŠคํŠธ 

TARGET_CSV : csvํŒŒ์ผ์ด ์žˆ๋Š” ์œ„์น˜ ๊ฒฝ๋กœ 

DEST_DIR : ์ตœ์ข…์ ์œผ๋กœ csvํŒŒ์ผ์ด ์ €์žฅ๋  ํด๋” ์œ„์น˜ ๊ฒฝ๋กœ 

HEADER : csv์˜ ํ—ค๋”๋ฅผ ์ถ”์ถœ ํ•ด๋†“์€ ๋ฆฌ์ŠคํŠธ 

 

 

 

- 1. ์ˆœ์ฐจ์‹คํ–‰ ์˜ˆ์ œ 

ํฌ์ŠคํŒ…์—์„œ๋Š” ์ฐจ๋ก€๋Œ€๋กœ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜์ง€๋งŒ ๊ณต๋ถ€ํ•  ๋•Œ๋Š” ๋’ค์—์„œ๋ถ€ํ„ฐ( (6) ๋ถ€ํ„ฐ ) ๊ฑฐ์Šฌ๋Ÿฌ์˜ค๋ฉฐ ๊ณต๋ถ€ํ•˜๊ธฐ

 

 

(1) ๊ตญ๊ฐ€๋ณ„ CSV ํŒŒ์ผ ์ €์žฅ 

def save_csv(data, filename):
    # ์ตœ์ข… ๊ฒฝ๋กœ ์ƒ์„ฑ 
    path = os.path.join(DEST_DIR, filename)

    with open(path, 'w', newline="") as fp:
        writer = csv.DictWriter(fp, fieldnames=HEADER)
        # Header Write
        writer.writeheader()
        # Dict to CSV write
        for row in data: 
            writer.writerow(row)

์ตœ์ข… csvํŒŒ์ผ์„ ์ €์žฅํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. ๊ตญ๊ฐ€๋ณ„๋กœ ๋งŒ๋“ค์–ด์ง„ ๋ฐ์ดํ„ฐ(data)์™€ ์ƒ์„ฑํ•  ํŒŒ์ผ์ด๋ฆ„(filename)์„ ์ธ์ž๋กœ ๋ฐ›๋Š”๋‹ค. 

 

 

(2) ๊ตญ๊ฐ€๋ณ„ ๋ถ„๋ฆฌ 

def get_sales_data(nt):
    with open(TARGET_CSV, 'r') as f:
        reader = csv.DictReader(f)
        # Dict๋ฅผ ๋ฆฌ์ŠคํŠธ๋กœ ์ ์žฌ 
        data = []
        # Header ํ™•์ธ 
        # print(reader.fieldnames)
        for r in reader:
            # OrderedDict ํ™•์ธ 
            # print(r)
            # ์กฐ๊ฑด์— ๋งž๋Š” ๊ตญ๊ฐ€๋งŒ ์‚ฝ์ž… 
            if r['Country'] == nt:
                data.append(r)
    return data

๊ตญ๊ฐ€์˜ ์ด๋ฆ„(nt)์„ ์ธ์ž๋กœ ๋ฐ›๋Š”๋‹ค. csvํŒŒ์ผ์„ ์—ด์–ด์„œ DictReader๋กœ reader์— ๋ฐ›์•„์ค€๋‹ค. Country๊ฐ€ nt๊ตญ๊ฐ€์ผ ๋•Œ data๋ฆฌ์ŠคํŠธ์— r์„ ๋„ฃ์–ด์ค€๋‹ค.  ์ด๋ ‡๊ฒŒ ๊ตญ๊ฐ€๋ณ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„๋ฆฌํ•ด ์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. 

 

 

(3) ์ค‘๊ฐ„ ์ƒํ™ฉ ์ถœ๋ ฅ

def show(text):
    print(text, end=' ')
    # ์ค‘๊ฐ„ ์ถœ๋ ฅ (๋ฒ„ํผ ๋น„์šฐ๊ธฐ)
    sys.stdout.flush()

๊ตญ๊ฐ€์˜ ์ด๋ฆ„์„ ๋ฐ›์•„์„œ ํ„ฐ๋ฏธ๋„์— ์ถœ๋ ฅํ•ด ์ฃผ์–ด ์ง„ํ–‰์ƒํ™ฉ์„ ์•Œ๋ ค์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. 

 

 

(4) ๊ตญ๊ฐ€ ๋ณ„ ๋ถ„๋ฆฌ ํ•จ์ˆ˜ ์‹คํ–‰ - (1) , (2) , (3) ํ•จ์ˆ˜ ์‚ฌ์šฉ

def separate_many(nt_list):
    for nt in sorted(nt_list):
        # ๋ถ„๋ฆฌ ๋ฐ์ดํ„ฐ 
        data = get_sales_data(nt)
        # ์ƒํ™ฉ ์ถœ๋ ฅ 
        show(nt)
        # ํŒŒ์ผ ์ €์žฅ 
        save_csv(data, nt.lower() + '.csv')

    return len(nt_list)

์—ฌ๊ธฐ์„œ for๋ฌธ์œผ๋กœ ๊ฐ ๊ตญ๊ฐ€๋ณ„ ์ด๋ฆ„์„ ์•ž์—์„œ ๋ณด์•˜๋˜ get_sales_data์— ๋„ฃ์–ด์ฃผ์–ด ๋ถ„๋ฆฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ csvํŒŒ์ผ๋กœ ์ €์žฅํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค. showํ•จ์ˆ˜๋กœ ์ง„ํ–‰์ƒํ™ฉ์„ ์ถœ๋ ฅํ•˜๊ณ , save_csvํ•จ์ˆ˜๋กœ ๊ฐ ๊ตญ๊ฐ€๋ณ„ csvํŒŒ์ผ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค. 

 

 

(5) ์‹œ๊ฐ„ ์ธก์ • ๋ฐ ๋ฉ”์ธํ•จ์ˆ˜ - (4) ํ•จ์ˆ˜ ์‚ฌ์šฉ

def main(separate_many):
    # ์‹œ์ž‘ ์‹œ๊ฐ„ 
    start_tm = time.time()
    # ๊ฒฐ๊ณผ ๊ฑด์ˆ˜ 
    result_cnt = separate_many(NATION_LS)
    # ์ข…๋ฃŒ ์‹œ๊ฐ„ 
    end_tm = time.time() - start_tm 

    msg = '\n{} csv separated in {:.2f}s'

    # ์ตœ์ข… ๊ฒฐ๊ณผ ์ถœ๋ ฅ 
    print(msg.format(result_cnt, end_tm))

๋“œ๋””์–ด mainํ•จ์ˆ˜์—์„œ๋Š” separate_manyํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตญ๊ฐ€๋ณ„ csvํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋„๋ก ํ•˜๊ณ  , ์ด์— ๋Œ€ํ•œ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜์—ฌ ์ถœ๋ ฅํ•ด์ค€๋‹ค. 

 

 

(6) ์‹คํ–‰ - (5) ํ•จ์ˆ˜ ์‚ฌ์šฉ

if __name__ == '__main__':
    main(separate_many)

Canada France Germany Israel Italy Maxico Norway Singapore Spain
9 csv separated in 21.09s

์ด๋ ‡๊ฒŒ mainํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์ฃผ๋ฉด ์•ž์—์„œ ๋งŒ๋“ค์–ด ๋†“์•˜๋˜ ํ•จ์ˆ˜๋“ค์ด ๋ชจ๋‘ ์‹คํ–‰๋˜๋ฉฐ 

๊ตญ๊ฐ€๋ณ„ csv ํŒŒ์ผ์ด ๋ชจ๋‘ ๋งŒ๋“ค์–ด ์ง„๋‹ค. 

 

 

 

 

 

 

 

 

 

 

 

 

*** Google Python GIL (Global Interpreter Lock) 

: GIL์€ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์ž์ฒด์—์„œ ๋ฝ์„ ๊ฑฐ๋Š” ๊ฒƒ์ด๋‹ค. 

 

<python GIL ๊ด€๋ จ๋ฌธ์„œ>

https://wiki.python.org/moin/GlobalInterpreterLock

 

GlobalInterpreterLock - Python Wiki

In CPython, the global interpreter lock, or GIL, is a mutex that protects access to Python objects, preventing multiple threads from executing Python bytecodes at once. The GIL prevents race conditions and ensures thread safety. A nice explanation of how t

wiki.python.org

 

 

- 2. concurrent.futures ๋ฐฉ๋ฒ•1 (ThreadPoolExecutor, ProcessPoolExecutor)

<concurent.futures ์ฐธ๊ณ ๋ฌธ์„œ>

https://docs.python.org/ko/3.7/library/concurrent.futures.html

 

concurrent.futures — ๋ณ‘๋ ฌ ์ž‘์—… ์‹คํ–‰ํ•˜๊ธฐ — Python 3.7.11 ๋ฌธ์„œ

์†Œ์Šค ์ฝ”๋“œ: Lib/concurrent/futures/thread.py์™€ Lib/concurrent/futures/process.py concurrent.futures ๋ชจ๋“ˆ์€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฝœ๋Ÿฌ๋ธ”์„ ์‹คํ–‰ํ•˜๋Š” ๊ณ ์ˆ˜์ค€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋น„๋™๊ธฐ ์‹คํ–‰์€ (ThreadPoolExecutor๋ฅผ ์‚ฌ์šฉ

docs.python.org

: map() ์‚ฌ์šฉ

: ์„œ๋กœ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ ๋˜๋Š” ํ”„๋กœ์„ธ์Šค์—์„œ ์‹คํ–‰ ๊ฐ€๋Šฅ 

: ๋‚ด๋ถ€ ๊ณผ์ •์„ ์•Œ ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ , ๊ณ ์ˆ˜์ค€์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•จ . 

...
from concurrent import futures

concurrent์˜ futres ๋ฅผ ์ถ”๊ฐ€๋กœ import ํ•ด์ค€๋‹ค. 

 

 

* (1) - (3) ์˜ ํ•จ์ˆ˜๋Š” ์•ž๊ณผ ๋™์ผํ•˜๋‹ค. 

 

(1) ๊ตญ๊ฐ€๋ณ„ CSV ํŒŒ์ผ ์ €์žฅ 

def save_csv(data, filename):
    # ์ตœ์ข… ๊ฒฝ๋กœ ์ƒ์„ฑ 
    path = os.path.join(DEST_DIR, filename)

    with open(path, 'w', newline="") as fp:
        writer = csv.DictWriter(fp, fieldnames=HEADER)
        # Header Write
        writer.writeheader()
        # Dict to CSV write
        for row in data: 
            writer.writerow(row)

(2) ๊ตญ๊ฐ€๋ณ„ ๋ถ„๋ฆฌ

def get_sales_data(nt):
    with open(TARGET_CSV, 'r') as f:
        reader = csv.DictReader(f)
        # Dict๋ฅผ ๋ฆฌ์ŠคํŠธ๋กœ ์ ์žฌ 
        data = []
        # Header ํ™•์ธ 
        # print(reader.fieldnames)
        for r in reader:
            # OrderedDict ํ™•์ธ 
            # print(r)
            # ์กฐ๊ฑด์— ๋งž๋Š” ๊ตญ๊ฐ€๋งŒ ์‚ฝ์ž… 
            if r['Country'] == nt:
                data.append(r)
    return data

(3) ์ค‘๊ฐ„ ์ƒํ™ฉ ์ถœ๋ ฅ

def show(text):
    print(text, end=' ')
    # ์ค‘๊ฐ„ ์ถœ๋ ฅ (๋ฒ„ํผ ๋น„์šฐ๊ธฐ)
    sys.stdout.flush()

 

 

(4) ๊ตญ๊ฐ€ ๋ณ„ ๋ถ„๋ฆฌ ํ•จ์ˆ˜ ์‹คํ–‰ - (1) , (2) , (3) ํ•จ์ˆ˜ ์‚ฌ์šฉ

def separate_many(nt):
    # ๋ถ„๋ฆฌ ๋ฐ์ดํ„ฐ 
    data = get_sales_data(nt)
    # ์ƒํ™ฉ ์ถœ๋ ฅ 
    show(nt)
    # ํŒŒ์ผ ์ €์žฅ 
    save_csv(data, nt.lower() + '.csv')

    return nt

1๋ฒˆ ๋ฐฉ๋ฒ•์ธ ์ˆœ์ฐจ์‹คํ–‰์—์„œ๋Š” for๋ฌธ์„ ์ด์šฉํ•˜์—ฌ ๊ตญ๊ฐ€๋ณ„ csvํŒŒ์ผ์„ ๋งŒ๋“ค์–ด๋ƒˆ๋‹ค. 2๋ฒˆ ๋ฐฉ๋ฒ•์—์„œ๋Š” mapํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตญ๊ฐ€ ์ด๋ฆ„ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ›์ง€ ์•Š๊ณ  , ๊ตญ๊ฐ€์ด๋ฆ„ ํ•˜๋‚˜์”ฉ์„ ๋ฐ›์•„ csvํŒŒ์ผ๋กœ ์ €์žฅํ•œ๋‹ค.  ์ตœ์ข…์ ์œผ๋กœ ๊ตญ๊ฐ€์ด๋ฆ„ ํ•˜๋‚˜(nt)๋ฅผ ๋ฆฌํ„ดํ•˜๋„๋ก ๋งŒ๋“ ๋‹ค.

 

 

 

(5) ์‹œ๊ฐ„ ์ธก์ • ๋ฐ ๋ฉ”์ธ ํ•จ์ˆ˜

futures.ThreadPoolExecutor() / futures.ProcessPoolExecutor 

 

 - ThreadPoolExecutor : GIL ์ข…์† 

def main(separate_many):
    # worker ๊ฐœ์ˆ˜
    worker = min(20, len(NATION_LS))
    # ์‹œ์ž‘ ์‹œ๊ฐ„
    start_tm = time.time()
    # ๊ฒฐ๊ณผ ๊ฑด์ˆ˜
    with futures.ThreadPoolExecutor(worker) as excutor:
        # map -> ์ž‘์—… ์ˆœ์„œ ์œ ์ง€, ์ฆ‰์‹œ ์‹คํ–‰
        result = excutor.map(separate_many, sorted(NATION_LS))
    # ์ข…๋ฃŒ ์‹œ๊ฐ„
    end_tm = time.time() - start_tm

    msg = '\n{} csv separated in {:.2f}s'
    # ์ตœ์ข… ๊ฒฐ๊ณผ ์ถœ๋ ฅ
    print(msg.format(len(list(result)), end_tm))
    
    
# ์‹คํ–‰
if __name__ == '__main__':
    main(separate_many)

 France Norway Spain Germany Maxico Canada Singapore Israel Italy 
 9 csv separated in 21.61s 

worker ๋ผ๋Š” ์ผ๊พผ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๊ณ , ThreadPoolExecutor()์˜ ์ธ์ž์— ๋„ฃ์–ด์ค€๋‹ค. ์—ฌ๊ธฐ์„œ result๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๊ฐ์ฒด๋กœ ์ €์žฅ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์ตœ์ข…๊ฒฐ๊ณผ ์ถœ๋ ฅ์—์„œ ๋ฆฌ์ŠคํŠธ์˜ ๊ธธ์ด๋ฅผ ์•Œ๊ธฐ ์œ„ํ•ด result๋ฅผ list ํƒ€์ž…์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ์–ด์•ผ ํ•œ๋‹ค. 

 

๋งŒ์•ฝ ๊ทธ๋ƒฅ len(result)๋กœ ์ž‘์„ฑํ•œ๋‹ค๋ฉด !

 File "c:/Users/./Desktop/python_high/chapter06_03_02.py", line 100, in main  
    result_cnt = len(excutor.map(separate_many, sorted(NATION_LS))) 
 TypeError: object of type 'generator' has no len() 

์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋Š” len() ๋ฅผ ๊ฐ–์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. 

 

 

 

 

- ProcessPoolExecutor : GIL ์šฐํšŒ, ๋ณ€๊ฒฝ ํ›„ -> ๋‚ด๋ถ€์ ์œผ๋กœ os.cpu_count() ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ (์šด์˜์ฒด์ œ ์ž์ฒด์—์„œ ์šฐํšŒ์—์„œ ๊ฐ -> ์†๋„๊ฐ€ ๋น ๋ฆ„ )

def main(separate_many):
    # worker ๊ฐœ์ˆ˜
    worker = min(20, len(NATION_LS))
    # ์‹œ์ž‘ ์‹œ๊ฐ„
    start_tm = time.time()
    # ๊ฒฐ๊ณผ ๊ฑด์ˆ˜
    with futures.ProcessPoolExecutor() as excutor:
        # map -> ์ž‘์—… ์ˆœ์„œ ์œ ์ง€, ์ฆ‰์‹œ ์‹คํ–‰
        result = excutor.map(separate_many, sorted(NATION_LS))
    # ์ข…๋ฃŒ ์‹œ๊ฐ„
    end_tm = time.time() - start_tm

    msg = '\n{} csv separated in {:.2f}s'
    # ์ตœ์ข… ๊ฒฐ๊ณผ ์ถœ๋ ฅ
    print(msg.format(len(list(result)), end_tm))
    
  
# ์‹คํ–‰
if __name__ == '__main__':
    main(separate_many)

 Norway Canada Germany France Spain Singapore Italy Maxico Israel 
 9 csv separated in 8.11s 

๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ProcessPoolExecutor๋ฅผ ํ•ด๋ณธ๋‹ค. ์‹œ๊ฐ„์ด ํ›จ์”ฌ ๋‹จ์ถ•๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

์–ธ์ œ ProcessPoolExecutor์“ฐ๊ณ , ThreadPoolExecutor์“ฐ๊ณ , ์ฝ”๋ฃจํ‹ด์„ ์“ฐ๋Š”์ง€๋ฅผ ์ƒ๊ฐํ•ด์•ผ ํ•œ๋‹ค. ProcessPoolExecutor์“ฐ๋ฉด cpu ์‚ฌ์šฉ๋Ÿ‰์ด ๊ธ‰๊ฒฉํžˆ ์ฆ๊ฐ€ํ•˜๊ณ  ๋น ๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฌํ•œ ๋ฉ€ํ‹ฐ ํ”„๋กœ์„ธ์‹ฑ์€ ๋‹จ๊ธฐ๊ฐ„์˜ ๋”ฅ๋Ÿฌ๋‹ ๊ณ ์† ์—ฐ์‚ฐ์— ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ThreadPoolExecutor์‚ฌ์šฉํ•˜๋ฉด ์†๋„๋Š” ๋” ๊ฑธ๋ฆฌ์ง€๋งŒ cpu ์‚ฌ์šฉ๋Ÿ‰์€ ์ž”์ž”ํ•˜๊ฒŒ ์ฆ๊ฐ€ํ•œ๋‹ค. ์ด ๋‘๊ฐ€์ง€์˜ ์ฐจ์ด๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ณ  , ์ ์ ˆํžˆ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. 

 

 

 

 

 

 

 

 

- 3. concurrent.futures ๋ฐฉ๋ฒ•2 (map()ํ•จ์ˆ˜ ๋Œ€์‹  for๋ฌธ์„ ์ด์šฉํ•˜์—ฌ ์„ธ๋ถ€์ ์ธ ๊ณผ์ • ์ฐ์–ด๋ณด๊ธฐ) 

 

* (1) - (3) ์˜ ํ•จ์ˆ˜๋Š” ์•ž๊ณผ ๋™์ผํ•˜๋‹ค. 

 

(4) ๊ตญ๊ฐ€ ๋ณ„ ๋ถ„๋ฆฌ ํ•จ์ˆ˜ ์‹คํ–‰ - (1) , (2) , (3) ํ•จ์ˆ˜ ์‚ฌ์šฉ

def main(separate_many):
    # worker ๊ฐœ์ˆ˜
    worker = min(20, len(NATION_LS))
    # ์‹œ์ž‘ ์‹œ๊ฐ„
    start_tm = time.time()
    # futures 
    futures_list = []
    # ๊ฒฐ๊ณผ ๊ฑด์ˆ˜
    # ProcessPoolExecutor : GIL ์šฐํšŒ, ๋ณ€๊ฒฝ ํ›„ -> ๋‚ด๋ถ€์ ์œผ๋กœ os.cpu_count() ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ (์šด์˜์ฒด์ œ ์ž์ฒด์—์„œ ์šฐํšŒ์—์„œ ๊ฐ)
    # ThreadPoolExecutor : GIL ์ข…์† 
    # with futures.ThreadPoolExecutor(worker) as excutor:
    with futures.ProcessPoolExecutor() as excutor:
        # submit -> callable ๊ฐ์ฒด ์Šค์ผ€์ฅด๋ง(์‹คํ–‰ ์˜ˆ์•ฝ) -> future 
        # Future -> as_complete(), result(), done(), cancelled() ์ฃผ๋กœ ์‚ฌ์šฉ 
        for nt in sorted(NATION_LS):
            # future ๋ฐ˜ํ™˜
            future = excutor.submit(separate_many, nt)
            # ์Šค์ผ€์ฅด๋ง
            futures_list.append(future)
            # ์ถœ๋ ฅ 
            # print('Scheduled for {} : {}'.format(nt, future))
            # print()

        for future in futures.as_completed(futures_list):
            result = future.result()
            done = future.done()
            cancelled = future.cancelled()
            # furue ๊ฒฐ๊ณผ ํ™•์ธ 
            print('Future Result : {}, Done : {}'.format(result, done))
            print('Future Cancelled : {}'.format(cancelled))

    # ์ข…๋ฃŒ ์‹œ๊ฐ„
    end_tm = time.time() - start_tm

    msg = '\n{} csv separated in {:.2f}s'
    # ์ตœ์ข… ๊ฒฐ๊ณผ ์ถœ๋ ฅ
    print(msg.format(len(futures_list), end_tm))

for๋ฌธ์œผ๋กœ ์ž‘์—…์„ ์ผ์ผ์ด ํ•˜๊ณ , ์„ธ๋ถ€์ ์œผ๋กœ ์ง„ํ–‰์ƒํ™ฉ๊ณผ ์–ด๋–ป๊ฒŒ ๋งˆ๋ฌด๋ฆฌ ๋˜์—ˆ๋Š”์ง€๋ฅผ ์•Œ๊ณ  ์‹ถ์„ ๋•Œ ์ด ๋ฐฉ๋ฒ•์„ ์“ด๋‹ค. 

2๋ฒˆ ๋ฐฉ๋ฒ•์—์„œ๋Š” map()ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ separate_many ํ•จ์ˆ˜๋กœ ๊ตญ๊ฐ€๋ณ„ csvํŒŒ์ผ์„ ์ €์žฅํ•ด ์ฃผ์—ˆ๋‹ค. 3๋ฒˆ ๋ฐฉ๋ฒ•์—์„œ๋Š” submit()ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ futre๋ณ€์ˆ˜์— ํ• ๋‹นํ•ด์ฃผ๊ณ  , ์ด future๋ฅผ futures_list์— append ํ•ด์ค€๋‹ค. 

 

futures.as_complted()์˜ ์ธ์ž์— futures_list๋ฅผ ๋„ฃ์–ด์ฃผ๊ณ , ๊ฐ๊ฐ์˜ future์— ๋Œ€ํ•œ result, done, cancelled ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. 

 

 

* ์‹คํ–‰ 

if __name__ == '__main__':
    main(separate_many)

 Germany Canada Future Result : Germany, Done : True 
 Future Cancelled : False 
 Norway Israel Future Result : Norway, Done : True 
 Italy Future Cancelled : False 
 Future Result : Canada, Done : True 
 Future Cancelled : False 
 Future Result : Israel, Done : True 
 Future Cancelled : False 
 Future Result : Italy, Done : True 
 Future Cancelled : False 
 Singapore France Future Result : Singapore, Done : True 
 Future Cancelled : False 
 Future Result : France, Done : True 
 Future Cancelled : False 
 Maxico Future Result : Maxico, Done : True 
 Future Cancelled : False 
 Spain Future Result : Spain, Done : True 
 Future Cancelled : False 

 9 csv separated in 8.60s 

์‹คํ–‰์„ ํ•ด๋ณด๋ฉด , result๋Š” ๊ฐ ๊ตญ๊ฐ€์˜ ์ด๋ฆ„(nt : separate_many์˜ ๋ฆฌํ„ด๊ฐ’), Done์€ ๋ชจ๋‘ True, Cancelled๋Š” ๋ชจ๋‘ False๊ฐ€ ๋‚˜์™€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด์™€ ๊ฐ™์ด for๋ฌธ๊ณผ submitํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ธ๋ถ€์ ์ธ ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜๋„ ์žˆ๋‹ค. 

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ)

 

 

<์ด์ „ ๊ธ€>

https://silvercoding.tistory.com/29

 

[python ์‹ฌํ™”] 12. ๋‚ด๋ถ€ iter ํ•จ์ˆ˜, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ(Generator)

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ) <์ด์ „ ๊ธ€> https://silvercoding.tistory.com/28 https://silvercoding.tistory.com/27 https://silvercoding.tistory.com/26 https://silvercoding.tistory.com/25..

silvercoding.tistory.com

 

 

* yield : ๋ฉ”์ธ ๋ฃจํ‹ด (์ˆœ์ฐจ์ง„ํ–‰ - ํ•˜๋‚˜์˜ ํ๋ฆ„) <-> ์„œ๋ธŒ๋ฃจํ‹ด (ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ์žˆ๋Š” ๊ณณ์œผ๋กœ) ์ด ๋ฃจํ‹ด ๋‘๊ฐœ๋ฅผ ๋™์‹œ์— ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฒŒ yield์ด๋‹ค. 

* ์ฝ”๋ฃจํ‹ด ์ œ์–ด , ์ฝ”๋ฃจํ‹ด  ์ƒํƒœ, ์–‘๋ฐฉํ–ฅ ๊ฐ’ ์ „์†ก (์–‘๋ฐฉํ–ฅ ํ†ต์‹ ) 

* ์„œ๋ธŒ ๋ฃจํ‹ด : ๋ฉ”์ธ๋ฃจํ‹ด์—์„œ ๋ฆฌํ„ด์— ์˜ํ•ด ํ˜ธ์ถœ ๋ถ€๋ถ„์œผ๋กœ ๋Œ์•„์™€ ๋‹ค์‹œ ํ”„๋กœ์„ธ์Šค 

* ์ฝ”๋ฃจํ‹ด : ๋ฃจํ‹ด ์‹คํ–‰ ์ค‘ ๋ฉˆ์ถค ๊ฐ€๋Šฅ -> ํŠน์ • ์œ„์น˜๋กœ ๋Œ์•„๊ฐ”๋‹ค๊ฐ€ -> ๋‹ค์‹œ ์›๋ž˜ ์œ„์น˜๋กœ ๋Œ์•„์™€ ์ˆ˜ํ–‰ ๊ฐ€๋Šฅ -> ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์คŒ 

*์“ฐ๋ ˆ๋“œ : ์‹ฑ๊ธ€์“ฐ๋ ˆ๋“œ -> ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ -> ๋ณต์žกํ•˜๋‹ค! (๊ณต์œ ๋˜๋Š” ์ž์›์— ๋Œ€ํ•œ ๊ต์ฐฉ์ƒํƒœ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ ์ฃผ์˜๊นŠ๊ฒŒ ์ฝ”๋”ฉํ•ด์•ผ ํ•จ) / ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋น„์šฉ ๋ฐœ์ƒ, ์ž์› ์†Œ๋น„ ๊ฐ€๋Šฅ์„ฑ ์ฆ๊ฐ€ 

 

 

- ์ฝ”๋ฃจํ‹ด ์˜ˆ์ œ1 

def coroutine1():
    print('>>> coroutine started.')
    i = yield 
    print('>>> coroutine received : {}'.format(i))

์ €๋ฒˆ ๊ธ€์—์„œ๋Š” yield i <-- ์ด๋Ÿฐ ์‹์œผ๋กœ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ , ์ด๋ฒˆ์—๋Š” i = yield ์˜ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์ธ ๋ฃจํ‹ด์—์„œ ๊ฐ’์„ ์ „๋‹ฌ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. 

 

 

* ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ์„ ์–ธ

c1 = coroutine1()
print('EX1-1 - ', c1, type(c1))

 EX1-1 -  <generator object coroutine1 at 0x000001430D3574F8> <class 'generator'> 

์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค. 

 

next(c1)
next(c1)

 >>> coroutine started. 
 >>> coroutine received : None 
 Traceback (most recent call last): 
  File "c:/Users/./Desktop/python_high/chapter06_02.py", line 35, in <module>  
    next(c1) 
 StopIteration 

์œ„์™€๊ฐ™์ด ๊ฐ’์„ ์ „์†กํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ None์„ ์ „์†กํ•œ๋‹ค. 

 

* ๊ฐ’ ์ „์†ก 

next(c1)
c1.send(100)

 >>> coroutine started. 
 >>> coroutine received : 100 
 Traceback (most recent call last): 
  File "c:/Users/./Desktop/python_high/chapter06_02.py", line 41, in <module>  
    c1.send(100) 
 StopIteration 

์ด๋ ‡๊ฒŒ next() ๋Œ€์‹  send()๋กœ ๊ฐ’์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

* ์ž˜๋ชป๋œ ์‚ฌ์šฉ 

c2 = coroutine1()
c2.send(100) # ์˜ˆ์™ธ ๋ฐœ์ƒ

 Traceback (most recent call last): 
  File "c:/Users/./Desktop/python_high/chapter06_02.py", line 45, in <module>  
    c2.send(100) # ์˜ˆ์™ธ ๋ฐœ์ƒ 
 TypeError: can't send non-None value to a just-started generator 

next()๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  , ์ฒ˜์Œ๋ถ€ํ„ฐ send๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค! ( ๋’ค์—์„œ next๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์•„๋„ ๋˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šธ ๊ฒƒ์ด๋‹ค. )

 

 

 

 

 

 

 

 

 

- ์ฝ”๋ฃจํ‹ด ์˜ˆ์ œ 2 

* GEN_CREATED : ์ฒ˜์Œ ๋Œ€๊ธฐ ์ƒํƒœ 

* GEN_RUNNING : ์‹คํ–‰ ์ƒํƒœ 

* GEN_SUSPENDED : yield ๋Œ€๊ธฐ ์ƒํƒœ 

* GEN_CLOSED : ์‹คํ–‰ ์™„๋ฃŒ ์ƒํƒœ 

 

def coroutine2(x):
    print('>>> coroutine started : {}'.format(x))
    y = yield x 
    print('>>> coroutine received : {}'.format(y))
    z = yield x + y 
    print('>>> coroutine received : {}'.format(z))

 

c3 = coroutine2(10)

coroutine2 ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ฐ์ฒด๋ฅผ ํ• ๋‹นํ•ด ์ค€๋‹ค. x๋Š” 10์œผ๋กœ ๋„ฃ์–ด์ค€๋‹ค. 

from inspect import getgeneratorstate
from typing_extensions import Literal

print('EX1-2 - ', getgeneratorstate(c3))

print(next(c3))

print('EX1-3 - ', getgeneratorstate(c3))

print(c3.send(15))
print(c3.send(20)) # ์˜ˆ์™ธ

 EX1-2 -  GEN_CREATED 

getgeneratorstate๋ฅผ ์ด์šฉํ•˜์—ฌ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ์˜ ์ƒํƒœ๋ฅผ ๊ฐ€์ ธ์™€์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์šฐ์„  ๊ฐ์ฒด๋งŒ ์ƒ์„ฑํ–ˆ์„ ๋•Œ ์ฒ˜์Œ ๋Œ€๊ธฐ ์ƒํƒœ์ž„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 
 >>> coroutine started : 10 
 10 

x๊ฐ’์ด ๋ฐ˜ํ™˜๋˜๊ณ , ์ด ์ƒํƒœ์—์„œ ๋Œ€๊ธฐํ•œ๋‹ค. 
 EX1-3 -  GEN_SUSPENDED 

yield ๋Œ€๊ธฐ ์ƒํƒœ ์ž„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 
 >>> coroutine received : 15 
 25 

๊ทธ๋‹ค์Œ send๋กœ 15๋ฅผ ๋ณด๋‚ด๋ฉด ๋ฉˆ์ถฐ์žˆ๋˜ yield ์ƒํƒœ์—์„œ y์— ๊ฐ’ 15๊ฐ€ ์ „๋‹ฌ๋œ๋‹ค. print๋ฌธ์œผ๋กœ 15๊ฐ€ ์ž˜ ์ „๋‹ฌ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ๋‹ค์Œ yield์˜ x + y ๊ฐ€ ๋ฐ˜ํ™˜๋˜๊ณ  ์ด์ƒํƒœ์—์„œ ๋ฉˆ์ถ˜๋‹ค. 

 >>> coroutine received : 20 

๋˜ ๋‹ค์‹œ send๋กœ 20์„ ๋ณด๋‚ด๋ฉด yield ๋Œ€๊ธฐ ์ƒํƒœ์—์„œ ๋ฉˆ์ถ”์–ด ์žˆ๋˜ z์— ๊ฐ’์ด ์ „๋‹ฌ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 Traceback (most recent call last): 
  File "c:/Users/./Desktop/python_high/chapter06_02.py", line 78, in <module>  
    print(c3.send(20)) # ์˜ˆ์™ธ 
 StopIteration 

๊ทธ๋‹ค์Œ yield๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๊ฒŒ ๋œ๋‹ค. 

 

 

 

 

 

 

 

 

 

 

- ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด

: next๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค! 

<๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํฌ์ŠคํŒ…>

https://silvercoding.tistory.com/26

 

[python ์‹ฌํ™”] 9. ๋ณ€์ˆ˜ ๋ฒ”์œ„, Closure, Decorator

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ) <์ด์ „ ๊ธ€> https://silvercoding.tistory.com/25 ์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์•Œ์•„๋ณผ ๊ฒƒ์ด๋‹ค. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ์–ด๋ ต๋‹ค๊ณ  ๋Š๋ผ๋Š” ๊ฒƒ์ด ๋‹น์—ฐํ•˜๋‹ค. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ

silvercoding.tistory.com

๋‚ด๋ถ€์ ์œผ๋กœ ๋Œ์•„๊ฐ€๋Š” ๊ฒŒ ํ•ญ์ƒ ํ—ท๊ฐˆ๋ ค์„œ ๋ณด๊ณ ์˜ค๊ธฐ

from functools import wraps

def coroutine(func):
    '''Decorator run until yield'''
    @wraps(func)
    def primer(*args, **kwargs):
        gen = func(*args, **kwargs)
        next(gen)
        return gen
    return primer

์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ฒ˜์Œ์— next๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ send๋กœ ๊ฐ’์„ ๋ณด๋‚ด๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋‚ฌ๋‹ค. ์ด๋ฒˆ์—๋Š” ์œ„ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ”๋กœ ๊ฐ’์„ ์ „์†กํ•˜๋„๋ก ๋งŒ๋“ ๋‹ค. 

@coroutine
def sumer():
    total = 0 
    term = 0 
    while True:
        term = yield total
        total += term
su = sumer()

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ @coroutine์„ ์ž‘์„ฑํ•ด ์ฃผ๊ณ , ๊ฐ์ฒด su๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค. 

print('EX2-1 - ', su.send(100))
print('EX2-2 - ', su.send(40))
print('EX2-3 - ', su.send(60))

 EX2-1 -  100 
 EX2-2 -  140 
 EX2-3 -  200 

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ์ธํ•ด next๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ๊ณ , yield์—์„œ ๋ฉˆ์ถ”์–ด ์žˆ๋Š” ์ƒํƒœ์ด๋‹ค. ์ด ์ƒํƒœ์—์„œ send๋กœ 100์„ ์ „์†กํ•˜๋ฉด term์— 100์ด ๋“ค์–ด๊ฐ€๊ณ , total์€ 0+100=100์ด ๋˜๊ณ , ๋‹ค์‹œ yield์—์„œ total์ด ๋ฐ˜ํ™˜๋˜๊ณ  ๋ฉˆ์ถ˜๋‹ค. ๊ทธ๋‹ค์Œ send๋กœ 40์„ ์ „์†กํ•˜๋ฉด term์— 40์ด ๋“ค์–ด๊ฐ€๊ณ , total=100+40=140์ด ๋˜์–ด ๋‹ค์‹œ yield๋ฅผ ๋งŒ๋‚ ๋•Œ๊นŒ์ง€ while๋ฌธ์ด ๋Œ์•„ total์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋ฉˆ์ถ˜๋‹ค. 60๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋Œ์•„๊ฐ€์„œ 200์ด ๋ฐ˜ํ™˜๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

 

 

 

 

- ์ฝ”๋ฃจํ‹ด ์˜ˆ์ œ 3 (์˜ˆ์™ธ ์ฒ˜๋ฆฌ) 

class SampleException(Exception):
    '''์„ค๋ช…์— ์‚ฌ์šฉํ•  ์˜ˆ์™ธ ์œ ํ˜•'''
def coroutine_except():
    print('>> coroutine started')
    try: 
        while True:
            try:
                x = yield
            except SampleException:
                print('-> SampleException handled. Continuing..') 
            else:
                print('-> coroutine received : {}'.format(x))
    finally:
        print('-> coroutine ending')

์œ„์—์„œ ๋งŒ๋“ค์–ด ๋†“์€ SampleException์„ ์ด์šฉํ•˜์—ฌ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค€๋‹ค. 

exe_co = coroutine_except()

๊ฐ์ฒด ์ƒ์„ฑ

print('EX3-1 - ', next(exe_co))
print('EX3-2 - ', exe_co.send(10))
print('EX3-3 - ', exe_co.send(100))
print('EX3-4 - ', exe_co.throw(SampleException))
print('EX3-5 - ', exe_co.send(1000))
print('EX3-6 - ', exe_co.close()) # GEN_CLOSED 
print('EX3-7 - ', exe_co.send(10)) # ์—๋Ÿฌ

 >> coroutine started 
 EX3-1 -  None 
 -> coroutine received : 10 
 EX3-2 -  None 
 -> coroutine received : 100 
 EX3-3 -  None 
 -> SampleException handled. Continuing.. 
 EX3-4 -  None 
 -> coroutine received : 1000 
 EX3-5 -  None 
 -> coroutine ending 
 EX3-6 -  None 
 Traceback (most recent call last): 
  File "c:/Users/./Desktop/python_high/chapter06_02.py", line 146, in <module>  
    print('EX3-7 - ', exe_co.send(10)) # ์—๋Ÿฌ 
 StopIteration 

EX3-4 ์—์„œ throw()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ์™ธ๋ฅผ ์žก๊ณ  ๋‹ค์‹œ yield๋กœ ๊ฐ€์„œ None์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋ฉˆ์ถ”์–ด ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‹ค์‹œ send๋กœ ๊ฐ’์„ ์ „์†กํ•ด๋„ ๋™์ž‘์„ ํ•˜๊ณ , ์ œ๋„ˆ๋ ˆ์ดํŠธ๋ฅผ ์•„์˜ˆ ๋๋‚ด๊ณ  ์‹ถ๋‹ค๋ฉด close()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. close()๋ฅผ ํ˜ธ์ถœ ํ•œ ํ›„ , send๋กœ ๊ฐ’์„ ์ „์†กํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

 

 

 

 

 

 

 

- ์ฝ”๋ฃจํ‹ด ์˜ˆ์ œ 4 (return) 

def averager_re():
    total = 0.0
    cnt = 0 
    avg = None
    while True:
        term = yield
        if term is None:
            break
        total += term
        cnt += 1
        avg = total / cnt 
    return 'Average : {}'.format(avg)
avger2 = averager_re()

๊ฐ’์œผ๋กœ None์„ ๋ณด๋‚ผ ๋•Œ๊นŒ์ง€ while๋ฌธ์ด ์‹คํ–‰๋˜๋„๋ก ํ•˜๊ณ  , ๋ณด๋‚ด๋Š” ๊ฐ’์„ ๋ชจ๋‘ ๋”ํ•ด์„œ ํ‰๊ท ์„ ๋‚ด์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. 

next(avger2)

avger2.send(10)
avger2.send(30)
avger2.send(50)

์œ„์™€ ๊ฐ™์ด ๊ฐ’์„ ์ „๋‹ฌํ•ด์ค€๋‹ค. 

try:
    avger2.send(None)
except StopIteration as e:
    print('EX4-1 - ', e.value)

 EX4-1 -  Average : 30.0 

None์„ ์ „์†กํ•˜์—ฌ while๋ฌธ์—์„œ ํƒˆ์ถœํ•˜๊ณ  , ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋กœ ํ•จ์ˆ˜์˜ ๋ฆฌํ„ด ๊ฐ’์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

 

 

 

 

 

 

 

 

- ์ฝ”๋ฃจํ‹ด ์˜ˆ์ œ 4 (yield from) (3.7 -> await

: ์ค‘์ฒฉ ์ฝ”๋ฃจํ‹ด ์ฒ˜๋ฆฌ 

 

(1) yield from ๋ฏธ์‚ฌ์šฉ 

def gen1():
    for x in 'AB':
        yield x 
    for y in range(1, 4):
        yield y

์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•ด ์ค€๋‹ค.

t1 = gen1()
print('EX5-1 - ', next(t1))
print('EX5-2 - ', next(t1))
print('EX5-3 - ', next(t1))
print('EX5-4 - ', next(t1))
print('EX5-5 - ', next(t1))
print('EX5-6 - ', next(t1)) # StopIteration

 EX5-1 -  A 
 EX5-2 -  B 
 EX5-3 -  1 
 EX5-4 -  2 
 EX5-5 -  3 
 Traceback (most recent call last): 
  File "c:/Users/./Desktop/python_high/chapter06_02.py", line 198, in <module> 
    print('EX5-6 - ', next(t1)) # StopIteration 
 StopIteration 

์•ž์—์„œ ํ•ด์™”๋˜ ๊ฒƒ ์ฒ˜๋Ÿผ next๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ๋” ์ด์ƒ ๋งŒ๋‚  yield๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด Stopiteration ์˜ˆ์™ธ๊ฐ€ ๋‚˜๊ฒŒ ๋œ๋‹ค. 

t2 = gen1()
print('EX5-7 - ', list(t2))

 EX5-7 -  ['A', 'B', 1, 2, 3] 

์ด๋ ‡๊ฒŒ ๋ฆฌ์ŠคํŠธ ๊ฐ์ฒด๋กœ ๋ฐ›์•„์ค„ ์ˆ˜๋„ ์žˆ๋‹ค. 

 

 

 

 

(2) yield from ์‚ฌ์šฉ 

def gen2():
    yield from 'AB'
    yield from range(1, 4)

์ด์™€ ๊ฐ™์ด yield from์„ ์‚ฌ์šฉํ•˜๋ฉด ์œ„์˜ ์˜ˆ์‹œ ์ฒ˜๋Ÿผ for๋ฌธ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋˜๊ณ  , ๊ฐ„๋‹จํ•˜๊ฒŒ ๋‘ ์ค„๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. 

t3 = gen2()
print('EX6-1 - ', next(t3))
print('EX6-2 - ', next(t3))
print('EX6-3 - ', next(t3))
print('EX6-4 - ', next(t3))
print('EX6-5 - ', next(t3))
print('EX5-6 - ', next(t3)) # StopIteration

 EX6-1 -  A 
 EX6-2 -  B 
 EX6-3 -  1 
 EX6-4 -  2 
 EX6-5 -  3 
 Traceback (most recent call last): 
  File "c:/Users/sooki/Desktop/python_high/chapter06_02.py", line 217, in <module> 
    print('EX5-6 - ', next(t3)) # StopIteration 
 StopIteration 

(1)๋ฒˆ ์˜ˆ์ œ์™€ ๋˜‘๊ฐ™์ด ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

t4 = gen2()
print('EX6-7 - ', list(t4))

 EX6-7 -  ['A', 'B', 1, 2, 3] 

list๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋™์ผํ•˜๊ฒŒ ๋‚˜์˜จ๋‹ค. 

 

 

 

 

 

* yield from ์˜ˆ์ œ +1 

def gen3_sub():
    print('Sub coroutine')
    x = yield 10 
    print('Recv: ', str(x))
    x = yield 100
    print('Recv: ', str(x))
    
def gen4_main():
    yield from gen3_sub()

์œ„์™€ ๊ฐ™์ด sub coroutine์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•ด ๋†“๊ณ  , main coroutine์—์„œ yield from ์œผ๋กœ ์ž‘์—…์„ ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. 

t5 = gen4_main()

print('EX7-1 - ', next(t5))
print('EX7-2 - ', t5.send(7))
print('EX7-3 - ', t5.send(77)) # ์˜ค๋ฅ˜

 Sub coroutine 
 EX7-1 -  10 
 Recv:  7 
 EX7-2 -  100 
 Recv:  77 
 Traceback (most recent call last): 
  File "c:/Users/sooki/Desktop/python_high/chapter06_02.py", line 247, in <module> 
    print('EX7-2 - ', t5.send(77)) 
 StopIteration 

 

 

 

 

 

 

 

 

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ)

 

 

<์ด์ „ ๊ธ€>

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์— ๋„ฃ์–ด ๊ทธ๋ฃน๋ณ„๋กœ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ)

 

 

<์ด์ „ ๊ธ€>

https://silvercoding.tistory.com/27

 

[python ์‹ฌํ™”] 10. copy & deep copy

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ) <์ด์ „ ๊ธ€> https://silvercoding.tistory.com/26 https://silvercoding.tistory.com/25 ์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์•Œ์•„๋ณผ ๊ฒƒ์ด๋‹ค. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ์–ด๋ ต๋‹ค๊ณ  ๋Š..

silvercoding.tistory.com

 

 

 

- Class  Getter & Setter 

* ํด๋ž˜์Šค ์„ ์–ธ 

class VectorP(object):
    def __init__(self, x, y):
        self.__x = float(x)
        self.__y = float(y)

    def __iter__(self):
        return (i for i in (self.__x, self.__y)) # Generator

 

 

* ๊ฐ์ฒด ์„ ์–ธ 

v = VectorP(20, 40)

 

* ์˜ค๋ฅ˜

print('EX1-1 - ', v.__x, v.__y)  # ---> ์ง์ ‘ ์ ‘๊ทผ ๋ถˆ๊ฐ€

 AttributeError: 'VectorP' object has no attribute '__x' 

 ์–ธ๋”๋ฐ” 2๊ฐœ๋กœ ์„ ์–ธํ•œ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋Š” ๊ฐ์ฒด๋ฅผ ํ†ตํ•œ ์ง์ ‘ ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅ ํ•˜๋‹ค. 

 

 

 

 

- Getter & Setter 

: ๋” ์•ˆ์ „ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. 

class VectorP(object):
    def __init__(self, x, y):
        self.__x = float(x)
        self.__y = float(y)

    def __iter__(self):
        return (i for i in (self.__x, self.__y)) # Generator

    @property
    def x(self):
        print('Called Property X')
        return self.__x

    @x.setter
    def x(self, v):
        print('Called Property X setter')
        self.__x = float(v)
    
    @property
    def y(self):
        print('Called Property Y')
        return self.__y

    @y.setter
    def y(self, v):
        print('Called Property Y setter')        
        if v < 30: 
            raise ValueError('30 Below is not possible')
        self.__y = float(v)

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ @property, @x.setter @y.setter ๋ฐ‘์— x์™€ y๋ฅผ ์ •์˜ํ•ด ์ค€๋‹ค. 

 

 

print('EX1-2 - ', dir(v), v.__dict__)
v.x = 10
print('EX1-3 - ', v.x, v.y)

 EX1-2 -  ['_VectorP__x', '_VectorP__y', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'x', 'y'] {'_VectorP__x': 20.0, '_VectorP__y': 40.0} 
 Called Property X 
 Called Property Y 
 EX1-3 -  10.0 40.0 

Getter์™€ Setter๋ฅผ ์ด์šฉํ•˜์—ฌ self.__x ๋ณ€์ˆ˜์— self.x ์˜ ํ˜•ํƒœ๋กœ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ด ์กŒ๋‹ค. v.x=10 ์„ ์ด์šฉํ•˜์—ฌ ๊ฐ’์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ๋˜ํ•œ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

# Iter ํ™•์ธ 
for val in v:
    print('EX1-4 - ', val)

 EX1-4 -  10.0 
 EX1-4 -  40.0 

๊ตฌํ˜„ํ•ด ๋†“์€ __iter__ ๋ฉ”์†Œ๋“œ๋ฅผ ํ™•์ธํ•˜์˜€๋‹ค. 

 

 

 

- __slot__ 

: ํŒŒ์ด์ฌ ์ธํ„ฐํ”„๋ฆฌํ„ฐ์—๊ฒŒ ํ†ต๋ณด , ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ๊ฐ€์ง€๋Š” ์†์„ฑ์„ ์ œํ•œ 

* __dict__ 

: ์†์„ฑ ์ตœ์ ํ™” -> ๋‹ค์ˆ˜ ๊ฐ์ฒด ์ƒ์„ฑ ์‹œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ๊ณต๊ฐ„ ๋Œ€ํญ ๊ฐ์†Œ 

: ํ•ด๋‹น ํด๋ž˜์Šค์— ๋งŒ๋“ค์–ด์ง„ ์ธ์Šคํ„ด์Šค ์†์„ฑ ๊ด€๋ฆฌ์— ๋”•์…”๋„ˆ๋ฆฌ ๋Œ€์‹  set ํ˜•ํƒœ๋ฅผ ์‚ฌ์šฉ 

 

class TestA(object):
    __slots__ = ('a', )

class TestB(object):
    pass

 

 

* ๊ฐ์ฒด ์ƒ์„ฑ 

use_slot = TestA()
no_slot = TestB()

 

* ์‚ฌ์šฉ

print('EX2-1 - ', use_slot)
# print('EX2-2 - ', use_slot.__dict__)  # ์†์„ฑ ๊ฐ’ ํ™•์ธ --> dictionary์ด๊ธฐ ๋•Œ๋ฌธ์— ์•ˆ๋จ 
print('EX2-3 - ', no_slot)
print('EX2-3 - ', no_slot.__dict__)

 EX2-1 -  <__main__.TestA object at 0x000001BE68801C78> 
 EX2-3 -  <__main__.TestB object at 0x000001BE68A4D6A0> 
 EX2-3 -  {} 

 

 

* ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋น„๊ต

import timeit

# ์ธก์ •์„ ์œ„ํ•œ ํ•จ์ˆ˜ ์„ ์–ธ 
def repeat_outer(obj):
    def repeat_inner():
        obj.a = 'TEST'
        del obj.a
    return repeat_inner

obj.a = 'TEST' ๋ฅผ ์„ ์–ธํ•˜๊ณ  obj.a๋ฅผ ์‚ญ์ œํ•˜๋Š” ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. 

 

print(min(timeit.repeat(repeat_outer(use_slot), number=100000))) 
print(min(timeit.repeat(repeat_outer(no_slot), number=100000)))

 0.015717999999999982 
 0.018735899999999972 

100000๋ฒˆ์„ ๋ฐ˜๋ณตํ•˜์—ฌ ๊ฐ€์žฅ ์ž‘์€ ์‹œ๊ฐ„์„ ์ถœ๋ ฅํ•ด ๋ณด์•˜์„ ๋•Œ, slot์„ ์‚ฌ์šฉํ•œ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๊ฐ€ ๋” ๋น ๋ฅธ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

- ๊ฐ์ฒด ์Šฌ๋ผ์ด์‹ฑ

class ObjectS:
    def __init__(self):
        self._numbers = [n for n in range(1, 100, 3)]

    def __len__(self):
        return len(self._numbers)

    def __getitem__(self, idx):
        return self._numbers[idx]

์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋ฅผ ๋ฆฌ์ŠคํŠธ ํƒ€์ž…์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ , __len__, __getitem__ ๋ฉ”์†Œ๋“œ๋ฅผ ์„ ์–ธํ•ด ๋†“์€ ObjectS ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. 

 

* ๊ฐ์ฒด ์ƒ์„ฑ

s = ObjectS()

 

print('EX3-1 - ', s.__dict__)    
print('EX3-2 - ', len(s))
print('EX3-3 - ', len(s._numbers))  # __len__ ์ด ์—†์œผ๋ฉด . 
print('EX3-4 - ', s[1:100])
print('EX3-5 - ', s[-1])
print('EX3-6 - ', s[::10])

 EX3-1 -  {'_numbers': [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49,  
 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97]} 

 EX3-2 -  33 
 EX3-3 -  33 

__len__ ๋ฉ”์†Œ๋“œ๋ฅผ ์„ ์–ธํ•ด ๋†“์ง€ ์•Š๋Š”๋‹ค๋ฉด EX3-3๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ์˜ ๊ธธ์ด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 
 EX3-4 -  [4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61,  
 64, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97] 
 EX3-5 -  97 
 EX3-6 -  [1, 31, 61, 91] 

 

__getitem__ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด ์ž์ฒด์—์„œ ์ธ๋ฑ์‹ฑ๊ณผ ์Šฌ๋ผ์ด์‹ฑ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค. ๋งŒ์•ฝ __getitem__ ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค.

 

 Traceback (most recent call last): 
  File "c:/Users/sooki/Desktop/python_high/chapter05_02.py", line 114, in <module>      
    print('EX3-4 - ', s[1:100])
 TypeError: 'ObjectS' object is not subscriptable 

 

 

 

 

- ํŒŒ์ด์ฌ ์ถ”์ƒ ํด๋ž˜์Šค 

https://docs.python.org/3/library/collections.abc.html

 

collections.abc — Abstract Base Classes for Containers — Python 3.9.6 documentation

collections.abc — Abstract Base Classes for Containers New in version 3.3: Formerly, this module was part of the collections module. Source code: Lib/_collections_abc.py This module provides abstract base classes that can be used to test whether a class

docs.python.org

1. ์ž์ฒด์ ์œผ๋กœ ๊ฐ์ฒด ์ƒ์„ฑ ๋ถˆ๊ฐ€ 

2. ์ƒ์†์„ ํ†ตํ•ด์„œ '์ž์‹ ํด๋ž˜์Šค' ์—์„œ ์ƒ์„ฑํ•ด์•ผ ํ•จ 

3. ๊ฐœ๋ฐœ๊ณผ ๊ด€๋ จ๋œ ๊ณตํ†ต๋œ ๋‚ด์šฉ (ํ•„๋“œ, ๋ฉ”์†Œ๋“œ) ์ถ”์ถœ ๋ฐ ํ†ตํ•ฉํ•ด์„œ ๊ณตํ†ต๋œ ๋‚ด์šฉ์œผ๋กœ ์ž‘์„ฑํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ

 

 

 

** Sequence ์ƒ์† ๋ฐ›์ง€ ์•Š์•˜์ง€๋งŒ, ์ž๋™์œผ๋กœ __iter__, __contain__ ๊ธฐ๋Šฅ ์ž‘๋™ 

** ๊ฐ์ฒด ์ „์ฒด๋ฅผ ์ž๋™์œผ๋กœ ์กฐ์‚ฌ -> ์‹œํ€€์Šค ํ”„๋กœํ† ์ฝœ 

class IterTestA():
    def __getitem__(self, idx):
        return range(1, 50, 2)[idx] # range(1, 50, 2)

__getitem__ ๋ฉ”์†Œ๋“œ๋ฅผ ์„ ์–ธํ•œ IterTestA ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. 

 

 

* ๊ฐ์ฒด ์ƒ์„ฑ

i1 = IterTestA()

 

print('EX4-1 - ', i1[4])
print('EX4-2 - ', i1[4:10])
print('EX4-3 - ', 3 in i1[1:10])  # __contain__ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•„๋„ ์‚ฌ์šฉ๋จ 
print('EX4-4 - ', [i for i in i1]) # ๊ตฌํ˜„ํ•˜์ง€ ์•Š์€ __iter__ ์‹คํ–‰

 EX4-1 -  9 
 EX4-2 -  range(9, 21, 2) 
 EX4-3 -  True 
 EX4-4 -  [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] 

์ธ๋ฑ์‹ฑ๊ณผ ์Šฌ๋ผ์ด์‹ฑ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก __getitem__ ๋ฉ”์†Œ๋“œ๋งŒ ์ƒ์„ฑ์„ ํ•ด ๋†“์•˜์ง€๋งŒ , 4-3, 4-4 ๊ฐ€ ์‹คํ–‰์ด ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. __contain__๊ณผ __iter__๋ฉ”์†Œ๋“œ๋ฅผ ํด๋ž˜์Šค ๋‚ด์— ์ƒ์„ฑํ•˜์ง€ ์•Š์•˜์–ด๋„ ์‹คํ–‰์ด ๋œ ๊ฒƒ์ด๋‹ค. 

 

 

 

 

- Sequence ์ƒ์† 

: ์š”๊ตฌ์‚ฌํ•ญ์ธ ์ถ”์ƒ๋ฉ”์†Œ๋“œ๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์•ผ ๋™์ž‘ 

from collections.abc import Sequence

class IterTestB(Sequence):
    def __getitem__(self, idx):
        return range(1, 50, 2)[idx] # range(1, 50, 2)

    def __len__(self, idx):
        return len(range(1, 50, 2)[idx])

Sequence๋ฅผ ์ƒ์† ๋ฐ›๋Š” IterTestB ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.  __getitem__, __len__ <--- ์ด ๋‘๊ฐœ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์œผ๋ฉด ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค. 

i2 = IterTestB()  # ---> __getitem__, __len__ ํ•จ์ˆ˜๊ฐ€ ์—†์œผ๋ฉด ๊ฐ์ฒด ์ƒ์„ฑ ๋ถˆ๊ฐ€. (๊ฐ•์ œ์„ฑ์„ ๋ˆ๋‹ค.)

๋‘๊ฐœ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ•˜๋‚˜๋ผ๋„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์œผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค. 

TypeError: Can't instantiate abstract class IterTestB with abstract methods __len__  

 

print('EX4-5 - ', i2[4])
print('EX4-6 - ', i2[4:10])
print('EX4-7 - ', 3 in i2[1:10])

 EX4-5 -  9 
 EX4-6 -  range(9, 21, 2) 
 EX4-7 -  True 

 

 

 

 

 

 

- abc ํ™œ์šฉ ์˜ˆ์ œ 

https://docs.python.org/ko/3/library/abc.html

 

abc — ์ถ”์ƒ ๋ฒ ์ด์Šค ํด๋ž˜์Šค — Python 3.9.6 ๋ฌธ์„œ

abc — ์ถ”์ƒ ๋ฒ ์ด์Šค ํด๋ž˜์Šค ์†Œ์Šค ์ฝ”๋“œ: Lib/abc.py ์ด ๋ชจ๋“ˆ์€, PEP 3119์—์„œ ์„ค๋ช…๋œ ๋Œ€๋กœ, ํŒŒ์ด์ฌ์—์„œ ์ถ”์ƒ ๋ฒ ์ด์Šค ํด๋ž˜์Šค (ABC) ๋ฅผ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค; ์ด๊ฒƒ์ด ์™œ ํŒŒ์ด์ฌ์— ์ถ”๊ฐ€๋˜์—ˆ

docs.python.org

import abc

class RandomMachine(abc.ABC): # metaclass=abc.ABCMeta(3.4 ์ดํ•˜)
    # __metaclass__ = abc.ABCMeta

    #์ถ”์ƒ ๋ฉ”์†Œ๋“œ  ---> ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๊ฐ€ ๋ถ™์€ ๊ฑด ๋ฌด์กฐ๊ฑด ์ž์‹ ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
    @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))

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ @abc.abstractmethod ๊ฐ€ ๋ถ™์€ ๋ฉ”์†Œ๋“œ๋Š” ๋ฌด์กฐ๊ฑด ์ž์‹ ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ ํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ด๋‹ค . load์™€ pick ๋ฉ”์†Œ๋“œ์— ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๊ฐ€ ๋‹ฌ๋ ค์žˆ๋‹ค. ์œ„์™€ ๊ฐ™์ด abc๋ฅผ ์ƒ์†๋ฐ›๋Š” ์ถ”์ƒํด๋ž˜์Šค์— ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ๋ฉ”์†Œ๋“œ์— ์ฃผ์„ ์„ค๋ช…์„ ๋‹ฌ์•„ ๋†“์œผ๋ฉด ์ž์‹ ํด๋ž˜์Šค์—์„œ ์ž์„ธํ•œ ๊ตฌํ˜„์„ ํ•˜๊ฒŒ๋˜๋Š” ๋ฐฉ์‹์ด๋‹ค. 

 

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()

์ด์™€ ๊ฐ™์ด abc๋ฅผ ์ƒ์†๋ฐ›์•˜๋˜ RandomMachine ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” CraneMachine ์„ ์ƒ์„ฑํ•œ๋‹ค. ์ž…๋ ฅํ•œ ์•„์ดํ…œ ๋ฆฌ์ŠคํŠธ ์ค‘์—์„œ ๋žœ๋ค ๋ฝ‘๊ธฐ๋ฅผ ํ•˜๋Š” ํด๋ž˜์Šค์ด๋‹ค. RandomMachine์—์„œ ๊ตฌํ˜„ํ•ด๋†“์•˜๋˜ ์ถ”์ƒ ๋ฉ”์†Œ๋“œ load, pick ํ•จ์ˆ˜๋Š” ํ•„์ˆ˜๋กœ ๊ตฌํ˜„ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. 

 

 

* ์„œ๋ธŒ ํด๋ž˜์Šค ํ™•์ธ 

print('EX5-1 - ', issubclass(RandomMachine, CraneMachine))
print('EX5-2 - ', issubclass(CraneMachine, RandomMachine))

 EX5-1 -  False 
 EX5-2 -  True 

issubclass๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ธŒํด๋ž˜์Šค์ธ์ง€ ํ™•์ธ ํ•ด๋ณธ๋‹ค. issubclass(RandomMachine, CraneMachine)์€ RandomMachine์ด CraneMachine์˜ ์„œ๋ธŒํด๋ž˜์Šค๋ƒ? ๋ผ๋Š” ๋œป์ด๋‹ค. 

 

 

* ์ƒ์† ๊ตฌ์กฐ ํ™•์ธ 

print('EX5-3 - ', CraneMachine.__mro__)  # ๊ฐ€๊ณ„๋„๋ฅผ ๋ณด์—ฌ์ค€๋‹ค. ์ƒ์†์„ ๋ฐ›์€ ์ˆœ์„œ๋ฅผ ๋ณด์—ฌ์คŒ

 EX5-3 -  (<class '__main__.CraneMachine'>, <class '__main__.RandomMachine'>, <class 'abc.ABC'>, <class 'object'>) 

 

 

* ๊ฐ์ฒด ์ƒ์„ฑ

cm = CraneMachine(range(1, 100)) # ์ถ”์ƒ ๋ฉ”์†Œ๋“œ ๊ตฌํ˜„ ์•ˆํ•˜๋ฉด ์—๋Ÿฌ

Sequence๋ฅผ ์ƒ์†ํ–ˆ์„ ๋•Œ __getitem__, __len__ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•„์ˆ˜์˜€๋‹ค๋ฉด, abc๋ฅผ ์ƒ์†ํ•  ๋•Œ๋Š” ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๋ฅผ ํ•„์ˆ˜๋กœ ๊ตฌํ˜„ํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฐ•์ œ์„ฑ์„ ๋ˆ๋‹ค. 

 

print('EX5-4 - ', cm._items)
print('EX5-5 - ', cm.pick())
print('EX5-6 - ', cm())
print('EX5-7 - ', cm.inspect()) # --> ๋ถ€๋ชจ์˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

 EX5-4 -  [53, 83, 95, 24, 97, 2, 43, 89, 85, 3, 59, 15, 78, 12, 46, 11, 29, 72, 6, 60, 41, 51, 1, 67, 10, 88, 5, 62, 33, 18, 55, 61, 13, 63, 90, 81, 32, 65, 86, 75, 94, 71, 93, 70, 26, 54, 31, 20, 91, 35, 34, 68, 57, 42, 23, 8, 77, 69, 36, 28, 99, 17, 98, 56, 44, 22, 14, 27, 30, 48, 37, 80, 87, 52, 49, 50, 40, 74, 25, 47, 96, 9, 45, 73, 4, 16, 21, 7, 82, 39, 58, 66, 84, 19, 79, 76, 38, 64, 92] 
 EX5-5 -  92 
 EX5-6 -  64 
 EX5-7 -  (38,) 

inspect๋ฉ”์†Œ๋“œ๋Š” ์ž์‹ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ํ•ด์ฃผ์ง€ ์•Š์•„๋„ ๋ถ€๋ชจ์˜ ํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋œ๋‹ค. 

 

 

 

 

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ)

 

<์ด์ „ ๊ธ€>

https://silvercoding.tistory.com/26

 

[python ์‹ฌํ™”] 9. ๋ณ€์ˆ˜ ๋ฒ”์œ„, Closure, Decorator

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ) <์ด์ „ ๊ธ€> https://silvercoding.tistory.com/25 ์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์•Œ์•„๋ณผ ๊ฒƒ์ด๋‹ค. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ์–ด๋ ต๋‹ค๊ณ  ๋Š๋ผ๋Š” ๊ฒƒ์ด ๋‹น์—ฐํ•˜๋‹ค. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ

silvercoding.tistory.com

 

 

- ์–•์€ ๋ณต์‚ฌ & is  vs  __eq__ (==) 

x = {'name': 'Kim','age': 33, 'city' : 'Seoul'}
y = x  # ---> ์–•์€ ๋ณต์‚ฌ

์šฐ์„  x์— ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์ €์žฅํ•œ๋‹ค. ๊ทธ๋‹ค์Œ ๋‹จ์ˆœํ•œ ๋ณต์‚ฌ๋ฅผ ํ•œ๋‹ค. 

print('EX2-1', id(x), id(y))  
print('EX2-2 - ', x == y)
print('EX2-3 - ', x is y)
print('EX2-4 - ', x, y)

 EX2-1 2324412065760 2324412065760 

์šฐ์„  id ๊ฐ’์„ ์ถœ๋ ฅํ•ด๋ณด๋‹ˆ ๋‘ ๊ฐ’์ด ์™„์ „ํžˆ ๊ฐ™์•˜๋‹ค. 

 EX2-2 -  True 

 EX2-3 -  True 

2-2์™€ 2-3์€ ์ง๊ด€์ ์œผ๋กœ ๋ด๋„ x์™€ y๊ฐ€ ๊ฐ™์€์ง€๋ฅผ ๋ฌผ์–ด๋ณด๋Š” ์ฝ”๋“œ์ธ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์ข…๋ฅ˜์˜ ํ™•์ธ๋ฒ•์ด๋‹ค. __eq__ (==) ์™€ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” x์™€ y์˜ ๊ฐ’์ด ๊ฐ™์€์ง€๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด๊ณ  , is๋Š” x์™€ y์˜ id๊ฐ’์ด ๊ฐ™์€์ง€๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด๋‹ค. 

 

** ์ •๋ฆฌ 

==(__eq__) : ๊ฐ’์„ ๋น„๊ต  vs  is : ๊ฐ์ฒด ์ฃผ์†Œ (์ •์ฒด์„ฑ) ๋น„๊ต

 

 EX2-4 -  {'name': 'Kim', 'age': 33, 'city': 'Seoul'} {'name': 'Kim', 'age': 33, 'city': 'Seoul'} 

์œ„ ์˜ˆ์ œ์—์„œ๋Š” ๊ฐ’, id ๋ชจ๋‘ ๊ฐ™๋‹ค. x์™€ y๋ฅผ ์ถœ๋ ฅํ•˜๋ฉด ๋‹น์—ฐํ•œ ๊ฒฐ๊ณผ๋กœ ๊ฐ™์€ ๋”•์…”๋„ˆ๋ฆฌ๊ฐ€ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

x์˜ ๊ฐ’์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์ถ”๊ฐ€ํ•˜๋ฉด y๋„ ๋ฐ”๋€”๊นŒ? id๊ฐ’์ด ๊ฐ™์œผ๋ฏ€๋กœ ๋ฐ”๋€” ๊ฒƒ์œผ๋กœ ์ถ”์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 

x['class'] = 10 
print('EX2-5 - ', x, y)

 

 EX2-5 -  {'name': 'Kim', 'age': 33, 'city': 'Seoul', 'class': 10} {'name': 'Kim', 'age': 33, 'city': 'Seoul', 'class': 10} 

x์— ๊ฐ’์„ ์ถ”๊ฐ€ํ–ˆ๋”๋‹ˆ y๋„ ๋˜‘๊ฐ™์ด ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. 

 

z = {'name': 'Kim','age': 33, 'city' : 'Seoul', 'class' : 10}

์ƒˆ ๋”•์…”๋„ˆ๋ฆฌ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ๋ณธ๋‹ค. ๊ฐ’์€ x์™€ ๊ฐ™๋„๋ก! 

print('EX2-6 - ', x, z)
print('EX2-7 - ', x is z)  # ๊ฐ™์€ ๊ฐ์ฒด๋ƒ 
print('EX2-8 - ', x is not z)  
print('EX2-9 - ', x == z)  # ๊ฐ’์ด ๊ฐ™๋ƒ

 EX2-6 -  {'name': 'Kim', 'age': 33, 'city': 'Seoul', 'class': 10} {'name': 'Kim', 'age': 33, 'city': 'Seoul', 'class': 10} 
 EX2-7 -  False 
 EX2-8 -  True 
 EX2-9 -  True 

x์™€ z๋ฅผ ๋น„๊ตํ•ด ๋ณด๋ฉด id๊ฐ’์€ ๋‹ค๋ฅด๊ณ , ๊ฐ’๋งŒ ๊ฐ™๋‹ค๊ณ  ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด ๊ฒฝ์šฐ์—๋Š” x์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜์—ฌ๋„ z์˜ ๊ฐ’์€ ๋ณ€ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค. (๋‹น์—ฐํ•œ ์†Œ๋ฆฌ) 

 

 

*** cf ) ํŠœํ”Œ (๋ถˆ๋ณ€ํ˜•) ๋น„๊ต 

tuple1 = (10, 15, [100, 1000])
tuple2 = (10, 15, [100, 1000])

print('EX3-1 - ', id(tuple1), id(tuple2))
print('EX3-2 - ', tuple1 is tuple2)
print('EX3-3 - ', tuple1 == tuple2)
print('EX3-4 - ', tuple1.__eq__(tuple2))

 EX3-1 -  2324415315832 2324415315544 
 EX3-2 -  False 
 EX3-3 -  True 
 EX3-4 -  True 

 

 

 

 

- Copy & DeepCopy (์–•์€ ๋ณต์‚ฌ , ๊นŠ์€ ๋ณต์‚ฌ) 

tl1 = [10, [100, 105], (5, 10, 15)]
tl2 = tl1
tl3 = list(tl1)

๋ฆฌ์ŠคํŠธ ์•ˆ์— ์ˆซ์ž, ๋ฆฌ์ŠคํŠธ, ํŠœํ”Œ์„ ๊ฐ๊ฐ ๋„ฃ์€ ํ›„, tl2์—๋Š” ์–•์€ ๋ณต์‚ฌ๋ฅผ , tl3์—๋Š” list์˜ ์ธ์ž์— ๋„ฃ์–ด ์ƒˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ์ค€๋‹ค. 

print('EX4-1 - ', tl1 == tl2)
print('EX4-2 - ', tl1 is tl2)
print('EX4-3 - ', tl1 == tl3)
print('EX4-4 - ', tl1 is tl3)

 EX4-1 -  True 
 EX4-2 -  True 
 EX4-3 -  True 
 EX4-4 -  False 

4-3๊ณผ 4-4์™€ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ๊ฐ’์€ ๊ฐ™์ง€๋งŒ, ๊ฐ์ฒด๋Š” ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. 

 

 

tl1.append(1000)
tl1[1].remove(105)

tl1์— 1000์„ ์ถ”๊ฐ€ํ•˜๊ณ , 1๋ฒˆ์งธ ๋ฆฌ์ŠคํŠธ์—์„œ 105๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ ! 

print('EX4-5 - ', tl1)
print('EX4-6 - ', tl2)
print('EX4-7 - ', tl3)

 EX4-5 -  [10, [100], (5, 10, 15), 1000] 
 EX4-6 -  [10, [100], (5, 10, 15), 1000] 
 EX4-7 -  [10, [100], (5, 10, 15)] 

tl2๋Š” ๊ฐ™์€ ๊ฐ์ฒด๋กœ ๋ณต์‚ฌ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— tl1๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ tl3๋Š” ๋ฐ˜๋งŒ ๋˜‘๊ฐ™๋‹ค! ์™œ ๊ทธ๋Ÿด๊นŒ? 

print(id(tl1[1])) # tl1๊ณผ tl3์˜ id๋Š” ๋‹ค๋ฅด์ง€๋งŒ ์•ˆ์— ์žˆ๋Š” ๋ฆฌ์ŠคํŠธ์˜ id๊ฐ’์€ ๊ฐ™๋‹ค. ! 
print(id(tl3[1]))

 2324415643528 
 2324415643528 

์•„ . tl1๊ณผ tl3 ์ž์ฒด ๊ฐ์ฒด์˜ id๊ฐ’์€ ๋‹ฌ๋ž์ง€๋งŒ, ๊ทธ ์•ˆ์— ์žˆ๋Š” 1๋ฒˆ์งธ ๋ฆฌ์ŠคํŠธ์˜ id๊ฐ’์€ ๊ฐ™์•˜๋‹ค. ์ ์  ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ํ•˜๋Š” ๋ณต์‚ฌ์˜ ํ—ˆ์ ์ด ๋ณด์ด๊ธฐ ์‹œ์ž‘ํ•œ๋‹ค. 

 

tl1[1] += [110, 120]
tl1[2] += (110, 120)

tl1์˜ ๋ฆฌ์ŠคํŠธ์™€ ํŠœํ”Œ์— ๊ฐ๊ฐ ๊ฐ’์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค. 

print('EX4-8 - ', tl1)
print('EX4-9 - ', tl2) # ํŠœํ”Œ ์žฌ ํ• ๋‹น (๊นฉ์ฒด ์ƒˆ๋กœ ์ƒ์„ฑ) ---> ๋ฐ์ดํ„ฐ๊ฐ€ ํ˜„์ €ํžˆ ๋งŽ์„ ๋–ˆ ์ฃผ์˜ ํ•ด์•ผ ํ•œ๋‹ค. ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋ฐ์ดํ„ฐ ์†์‹ค์ด ์žˆ์„ ์ˆ˜๋„ ์žˆ๊ณ  , ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋” ์ฐจ์ง€ํ•  ์ˆ˜๋„ ์žˆ๊ฒŒ ๋˜๊ธฐ ๋•Œ๋ฌธ !
print('EX4-10 - ', tl3)

 EX4-8 -  [10, [100, 110, 120], (5, 10, 15, 110, 120), 1000] 
 EX4-9 -  [10, [100, 110, 120], (5, 10, 15, 110, 120), 1000] 
 EX4-10 -  [10, [100, 110, 120], (5, 10, 15)] 

์šฐ์„  tl1, tl2๋Š” ์—ฌ๊ธฐ์„œ๋„ ๋˜‘๊ฐ™์ด ์›€์ง์ธ ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ tl3์—์„œ๋Š” ์กฐ๊ธˆ ์ด์ƒํ•œ ํ˜„์ƒ์ด ์ผ์–ด๋‚ฌ๋‹ค. ๋ฆฌ์ŠคํŠธ๋Š” ๊ฐ’์ด ์ถ”๊ฐ€๋˜์—ˆ์ง€๋งŒ , ํŠœํ”Œ์€ ๊ฐ’์ด ์ถ”๊ฐ€๋˜์ง€ ์•Š์•˜๋‹ค. ๋‹ต์€ ์ฝ”๋“œ ์ฃผ์„์— ์จ์žˆ๋“ฏ์ด, ํŠœํ”Œ์€ ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜์—ฌ ์žฌ ํ• ๋‹น์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ, ์ดํ•ด๋ฅผ ์œ„ํ•˜์—ฌ id๊ฐ’์„ ์ถœ๋ ฅํ•ด๋ณด์•˜๋‹ค. 

 

# ๋ฆฌ์ŠคํŠธ, ํŠœํ”Œ์— ๊ฐ’ ์ถ”๊ฐ€ ์ „ 
print(id(tl1[2]))
print(id(tl2[2]))
print(id(tl3[2]))

...

# ๋ฆฌ์ŠคํŠธ, ํŠœํ”Œ์— ๊ฐ’ ์ถ”๊ฐ€ ํ›„
print(id(tl1[2]))
print(id(tl2[2]))
print(id(tl3[2]))

 1367137568664 
 1367137568664 
 1367137568664 

 

 1367137218056 
 1367137218056 
 1367137568664 

๋ฆฌ์ŠคํŠธ์ฒ˜๋Ÿผ tl1, tl3์˜ ํŠœํ”Œ id๊ฐ’์€ ๊ฐ™์•˜๋‹ค. ํŠœํ”Œ์—์„  ์ด๊ฒŒ ์ด์Šˆ๊ฐ€ ๋˜๋Š” ๊ฒƒ์ด๋‹ค! tl1[2] += (110, 120) <--- ์ด ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋ฉด ํŠœํ”Œ์ด ์žฌํ• ๋‹น๋˜์–ด ์ƒˆ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. ๊ทธ๋ž˜์„œ id๊ฐ’์„ ๋ณด๋ฉด ์ด ์ฝ”๋“œ ์ „๊ณผ ํ›„์˜ tl1, tl2 id๊ฐ’์ด ๋‹ฌ๋ผ์ง„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ „๊ณผ ๊ฐ™์€ id๊ฐ’์„ ๊ฐ€์ง„ tl3์˜ ํŠœํ”Œ์€ ๋ณ€ํ™”ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด๋‹ค. 

 

 

 

 

*** copy & Deep copy (๊นŠ์€ ๋ณต์‚ฌ) ์‹ค์Šตํ•ด๋ณด๊ธฐ 

(ex) ์žฅ๋ฐ”๊ตฌ๋‹ˆ ํด๋ž˜์Šค 

class Basket:
    def __init__(self, products=None):
        if products is None:
            self._products = []
        else:
            self._products = list(products)  # ์ƒˆ๋กœ์šด ๊ฐ์ฒด ์ƒ์„ฑ

    def put_prod(self, prod_name):
        self._products.append(prod_name)

    def del_prod(self, prod_name):
        self._products.remove(prod_name)

_products์— ๋ฌผ๊ฑด์„ ๋‹ด๊ณ , put_prod ๋ฉ”์†Œ๋“œ๋กœ ๋ฌผ๊ฑด ์ถ”๊ฐ€ , del_prod ๋ฉ”์†Œ๋“œ๋กœ ๋ฌผ๊ฑด ์‚ญ์ œ๋ฅผ ํ•˜๋Š” ํด๋ž˜์Šค ์ƒ์„ฑ! 

import copy

basket1 = Basket(['Apple', 'Bag', 'TV', 'Snack', 'Water'])
basket2 = copy.copy(basket1)  # ์–•์€ ๋ณต์‚ฌ 
basket3 = copy.deepcopy(basket1)  # ๊นŠ์€ ๋ณต์‚ฌ ---> ๊ฐ์ฒด ์•ˆ์— ์žˆ๋Š” ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๊นŒ์ง€ ์ฐธ์กฐ

copy๋ฅผ importํ•˜์—ฌ ์–•์€ ๋ณต์‚ฌ(copy.copy) ์™€ ๊นŠ์€ ๋ณต์‚ฌ(copy.deepcopy) ๋ฅผ ํ•ด๋ณธ๋‹ค. 

print('EX5-1 - ', id(basket1), id(basket2), id(basket3))
print('EX5-2 - ', id(basket1._products), id(basket2._products), id(basket3._products))

 EX5-1 -  1367137770520 1367137770464 1367137771304 
 EX5-2 -  1367137799240 1367137799240 1367137626888 

copy๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด ์ž์ฒด๋Š” ๋ชจ๋‘ ๋‹ค๋ฅด๊ฒŒ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. EX5-2์—์„œ ์–•์€ ๋ณต์‚ฌ์™€ ๊นŠ์€๋ณต์‚ฌ์˜ ์ฐจ์ด์ ์ด ๋ณด์ธ๋‹ค. deepcopy๋Š” ๊ฐ์ฒด ์•ˆ์— ์žˆ๋Š” ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๊นŒ์ง€ ์ฐธ์กฐ๋ฅผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€์ˆ˜์˜ ๊ฐ์ฒด๊นŒ์ง€ id์˜ ๊ฐ’์ด ๋‹ค๋ฅด๋‹ค! 

 

basket1.put_prod('Orange')
basket2.del_prod('Snack')

basket1์— Orange๋ฅผ ๋„ฃ๊ณ , Snack์„ ์‚ญ์ œํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋Š”์ง€ ํ™•์ธํ•ด ๋ณด์ž! 

# ๋น…๋ฐ์ดํ„ฐ๋‚˜, ์›น๊ฐœ๋ฐœํ•  ๋–„ ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค. 
print('EX5-3 - ', basket1._products)
print('EX5-4 - ', basket2._products)  
print('EX5-5 - ', basket3._products)

 EX5-3 -  ['Apple', 'Bag', 'TV', 'Water', 'Orange'] 
 EX5-4 -  ['Apple', 'Bag', 'TV', 'Water', 'Orange'] 
 EX5-5 -  ['Apple', 'Bag', 'TV', 'Snack', 'Water'] 

์ด๋ ‡๊ฒŒ basket1๊ณผ basket2๋Š” ์„œ๋กœ ์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค. ๊นŠ์€๋ณต์‚ฌ๋ฅผ ํ•œ basket3๋Š” ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค. 

์ด๋Š” ๋น…๋ฐ์ดํ„ฐ ๋˜๋Š” ์›น๊ฐœ๋ฐœ์„ ํ•  ๋•Œ ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋น…๋ฐ์ดํ„ฐ ๋ถ„์„์„ ํ•  ๋•Œ ์›๋ณธ์€ ์†์ƒ์‹œํ‚ค์ง€ ์•Š๊ณ  ๋ณต์‚ฌ๋ฅผ ํ•˜์—ฌ ์ „์ฒ˜๋ฆฌ๋ฅผ ํ•  ๊ฒฝ์šฐ ์–•์€ ๋ณต์‚ฌ๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด ์ƒ๊ฐ๋งŒ ํ•ด๋„ ์•„์ฐ”ํ•˜๋‹ค. 

 

 

 

- ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ „๋‹ฌ ์ฃผ์˜ 

def mul(x, y):
    x += y
    return x

x์— y๋ฅผ ๋”ํ•ด์„œ x์— ๋„ฃ๊ณ , x๋ฅผ returnํ•ด์ฃผ๋Š” mul ํ•จ์ˆ˜ ์ƒ์„ฑ 

x = 10 
y = 5

print('EX6-1 - ', mul(x, y), x, y)

 EX6-1 -  15 10 5 

ํ•จ์ˆ˜ ์•ˆ์˜ x๊ฐ€ 15๋ผ๊ณ  ํ•ด์„œ ์ „์—ญ๋ณ€์ˆ˜ x์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์ง€๋Š” ์•Š๋Š”๋‹ค. 

 

 

* ๊ฐ€๋ณ€ํ˜• a -> ์›๋ณธ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ/ ํ•จ์ˆ˜์— ์ „๋‹ฌํ•  ๋•Œ ์›๋ณธ์˜ ์ฃผ์†Œ๊นŒ์ง€ ๋„˜๊น€

a = [10, 100]
b = [5, 10]

print('Ex6-2 - ', mul(a, b), a, b)  # ---> ํ™•์žฅ! ! ! ! !

 Ex6-2 -  [10, 100, 5, 10] [10, 100, 5, 10] [5, 10] 

ํ•˜์ง€๋งŒ ๊ฐ€๋ณ€ํ˜•์ธ ๋ฆฌ์ŠคํŠธ ํƒ€์ž…์˜ a๋ฅผ mul์— ๋„ฃ์œผ๋ฉด ์ „์—ญ๋ณ€์ˆ˜์ธ a์˜ ๊ฐ’๊นŒ์ง€ ๋ณ€ํ•ด๋ฒ„๋ฆฐ๋‹ค. ์ฆ‰ ์›๋ณธ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ํ•จ์ˆ˜์— ์ด ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์›๋ณธ์˜ ์ฃผ์†Œ๊นŒ์ง€ ๋„˜๊ธฐ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

 

 

* ๋ถˆ๋ณ€ํ˜• c ---> ์›๋ณธ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์•ˆ๋จ

c = (10, 100)
d = (5, 10)
print('Ex6-2 - ', mul(c, d), c, d)

๋ถˆ๋ณ€ํ˜•์ธ ํŠœํ”Œํƒ€์ž…์˜ c๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ์›๋ณธ ๋ฐ์ดํ„ฐ์˜ ๋ณ€๊ฒฝ์ด ๋˜์ง€ ์•Š๋Š”๋‹ค. ์œ„์—์„œ ๋ฐฐ์› ๋“ฏ์ด ํŠœํ”Œ์˜ ๋‚ด์šฉ์ด ๊ฐฑ์‹ ๋  ๋•Œ๋Š” ์ƒˆ๋กœ์šด ์ฃผ์†Œ์— ํ• ๋‹น์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

 

 

 

 

- ํŒŒ์ด์ฌ ๋ถˆ๋ณ€ํ˜• ์˜ˆ์™ธ 

: str, bytes, frozenset, Tuple ---> ์‚ฌ๋ณธ ์ƒ์„ฑ X ---> ์ฐธ์กฐ ๋ฐ˜ํ™˜ (๊ฐ™์€ ๊ฐ’์ด๋ฉด id ๋„ ๊ฐ™๋‹ค) 

tt1 = (1, 2, 3, 4, 5)
tt2 = tuple(tt1)
tt3 = tt1[:]

์ด๋ฒˆ์—” ํŠœํ”Œ์„ ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณต์‚ฌํ•˜์—ฌ tt2์™€ tt3๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค. 

print('EX7-1 - ', tt1 is tt2, id(tt1), id(tt2))
print('EX7-2 - ', tt1 is tt3, id(tt1), id(tt3))

 EX7-1 -  True 1367134857000 1367134857000 
 EX7-2 -  True 1367134857000 1367134857000 

๋ฆฌ์ŠคํŠธ๋Š” ์œ„์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์ƒˆ๋กœ์šด ์ฃผ์†Œ๊ฐ€ ๋ถ€์—ฌ๋์—ˆ๋‹ค. ํŠœํ”Œ์€ ๋ถˆ๋ณ€ํ˜•์ด๋ฏ€๋กœ ๊ฐ™์€ ๊ฐ’์ด๋ฉด id๋Š” ๊ฐ™๋‹ค. ๋”ฐ๋ผ์„œ ๋ชจ๋“  id๊ฐ’์ด ๊ฐ™๊ฒŒ ๋‚˜์™”๋‹ค. ํŠœํ”Œ์€ ๋ถˆ๋ณ€ํ˜•์ด๊ธฐ ๋•Œ๋ฌธ์— ํŠœํ”Œ์— ํŠœํ”Œ์„ ๋”ํ•  ๋•Œ ๊ธฐ์กด ํŠœํ”Œ์— ๊ฐ’์ด ์ถ”๊ฐ€๋˜๋Š” ๊ฐœ๋…์ด๊ธฐ ๋ณด๋‹ค๋Š” ์ƒˆ๋กœ์šด ํŠœํ”Œ ๊ฐ์ฒด๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฒƒ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.  

 

tt4 = (10, 20, 30, 40, 50)
tt5 = (10, 20, 30, 40, 50)
ss1 = 'Apple'
ss2 = 'Apple'

ํŠœํ”Œ๊ณผ ๋˜๋‹ค๋ฅธ ๋ถˆ๋ณ€ํ˜• str๋กœ ๊ฒ€์ฆ์„ ํ•ด๋ณด๊ณ  ๋งˆ์นœ๋‹ค. 

print('EX7-3 - ', tt4 is tt5, tt4 == tt5, id(tt4), id(tt5))
print('EX7-4 - ', ss1 is ss2, ss1 == ss2, id(ss1), id(ss2))

 EX7-3 -  True True 1367137216648 1367137216648 
 EX7-4 -  True True 1367137769320 1367137769320 

๊ฐ’์ด ๊ฐ™์œผ๋ฉด ๋‹ค๋ฅธ ๋ณ€์ˆ˜์— ๋”ฐ๋กœ ์ƒ์„ฑ์„ ํ•ด๋„ ๊ฐ™์€ ์ฃผ์†Œ๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. 

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ)

 

<์ด์ „ ๊ธ€>

https://silvercoding.tistory.com/25

 

์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์•Œ์•„๋ณผ ๊ฒƒ์ด๋‹ค. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ์–ด๋ ต๋‹ค๊ณ  ๋Š๋ผ๋Š” ๊ฒƒ์ด ๋‹น์—ฐํ•˜๋‹ค. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์— ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—๋Š” ๋ณ€์ˆ˜์˜ ๋ฒ”์œ„์™€ ํด๋กœ์ € ๊ฐœ๋…์„ ์•Œ์•„์•ผ ํ•˜๋ฏ€๋กœ ์ด ๋‘˜์„ ๋จผ์ € ์‚ดํŽด๋ณด์ž.

 

- ํŒŒ์ด์ฌ ๋ณ€์ˆ˜ ๋ฒ”์œ„ 

*** ์ „์—ญ๋ณ€์ˆ˜ vs ์ง€์—ญ๋ณ€์ˆ˜ ์ฐธ๊ณ  

https://wikidocs.net/62

 

์œ„ํ‚ค๋…์Šค

์˜จ๋ผ์ธ ์ฑ…์„ ์ œ์ž‘ ๊ณต์œ ํ•˜๋Š” ํ”Œ๋žซํผ ์„œ๋น„์Šค

wikidocs.net

์—ฌ๊ธฐ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์ •๋ฆฌ๊ฐ€ ๋˜์–ด์žˆ๋‹ค! 

 

์ง์ ‘ ์‹ค์Šตํ•ด๋ณด์ž 

# ์˜ˆ์ œ 1
def func_v1(a):
    print(a)
    print(b)


# ์˜ค๋ฅ˜
# func_v1(5)

 Traceback (most recent call last): 
  File "c:/Users/./Desktop/python_high/chapter04_02.py", line 19, in <module>
    func_v1(5) 
  File "c:/Users/./Desktop/python_high/chapter04_02.py", line 15, in func_v1       
    print(b) 
 NameError: name 'b' is not defined 

 

์˜ˆ์ œ1๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜๊ณ , ํ˜ธ์ถœํ•˜๋ฉด ๋‹น์—ฐํ•œ ๊ฒฐ๊ณผ๋กœ NameError๊ฐ€ ๋‚œ๋‹ค. b๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š์€๋ฐ b๋ฅผ ์ถœ๋ ฅํ•˜๋ผ๊ณ  ์ž‘์„ฑํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

 

 

# ์˜ˆ์ œ 2 
b = 10

def func_v2(a):
    print(a)
    print(b)

func_v2(5)

๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ํ•จ์ˆ˜ ๋ฐ–์— b๋ฅผ ์„ ์–ธํ•˜๊ณ  ํ•จ์ˆ˜ ์•ˆ์—์„œ b๋ฅผ ์ถœ๋ ฅํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? 

 5  
 10  

์œ„์™€ ๊ฐ™์ด ์ถœ๋ ฅ์ด ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ์˜ b๋ฅผ ์ „์—ญ๋ณ€์ˆ˜๋ผ๊ณ  ํ•œ๋‹ค.

 

 

# ์˜ˆ์ œ3 
b = 10

def func_v3(a):
    print(a)
    print(b)
    b = 5
    
func_v3(5)

์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? 

Traceback (most recent call last):
  File "c:/Users/sooki/Desktop/python_high/chapter04_02.py", line 42, in <module>      
    func_v3(5) 
  File "c:/Users/./Desktop/python_high/chapter04_02.py", line 39, in func_v3       
    print(b) 
UnboundLocalError: local variable 'b' referenced before assignment

์˜ค! UnboundLocalError ๊ฐ€ ๋‚œ๋‹ค. ํ• ๋‹น๋˜๊ธฐ ์ „์— ์ง€์—ญ๋ณ€์ˆ˜ 'b'๊ฐ€ ์ฐธ์กฐ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. 

 

ํ•จ์ˆ˜ ๋‚ด์— b๊ฐ€ ์žˆ๋Š” ๊ฑด ์ฒดํฌ๊ฐ€ ๋˜์—ˆ๋Š”๋ฐ, b์— ๊ฐ’์„ ํ• ๋‹นํ•˜๊ธฐ ์ „์— b๋ฅผ ์ถœ๋ ฅํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค. 

๊ฐ™์€ ์ด๋ฆ„์˜ ์ „์—ญ๋ณ€์ˆ˜์™€ ์ง€์—ญ๋ณ€์ˆ˜๊ฐ€ ์žˆ์œผ๋ฉด ํ•จ์ˆ˜ ๋‚ด์—์„œ๋Š” ์ง€์—ญ๋ณ€์ˆ˜๊ฐ€ ์šฐ์„ ์ด๋ฉฐ, ๋Ÿฐํƒ€์ž„์˜ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๊ฐ€ b๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ์ฒดํฌํ–ˆ์ง€๋งŒ, ํ• ๋‹น์€ ์œ„์—์„œ๋ถ€ํ„ฐ ์•„๋ž˜๋กœ ์ด๋ฃจ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

* ์ฆ๋ช…

from dis import dis

print('EX1-1 - ')
print(dis(func_v3))

EX1-1 -
 38           0 LOAD_GLOBAL              0 (print) 
              2 LOAD_FAST                0 (a) 
              4 CALL_FUNCTION            1 
              6 POP_TOP 

 39           8 LOAD_GLOBAL              0 (print) 
             10 LOAD_FAST                1 (b) 
             12 CALL_FUNCTION            1 
             14 POP_TOP 
 
 40          16 LOAD_CONST               1 (5) 
             18 STORE_FAST               1 (b)  
             20 LOAD_CONST               0 (None) 
             22 RETURN_VALUE 
 None 

 

 

 

- Closure (ํด๋กœ์ €) 

1. ๋ฐ˜ํ™˜๋˜๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ ์„ ์–ธ๋œ ์—ฐ๊ฒฐ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์ฐธ์กฐํ•˜๋Š” ๋ฐฉ์‹ 

2. ๋ฐ˜ํ™˜ ๋‹น์‹œ ํ•จ์ˆ˜์˜ ์œ ํšจ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๋ณ€์ˆ˜ ๋˜๋Š” ๋ฉ”์†Œ๋“œ์— ์ง์ ‘ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅ 

 

๊ธ€๋กœ ์ฝ์œผ๋ฉด ์ดํ•ด๊ฐ€ ์–ด๋ ค์šฐ๋‹ˆ ์ง์ ‘ ์‹ค์Šตํ•ด๋ณด๊ธฐ . 

a = 10 

print('EX2-1 - ', a + 10)
print('EX2-2 - ', a + 100)
print('EX2-3 - ', sum(range(1, 51)))
print('EX2-4 - ', sum(range(51, 101)))

 EX2-1 -  20 
 EX2-2 -  110 
 EX2-3 -  1275 
 EX2-4 -  3775 

a๋ผ๋Š” ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ  , ๋”ฐ๋กœ ๋”ฐ๋กœ 10, 100์„ ๋”ํ•˜๊ณ  ์ถœ๋ ฅํ•˜๋ฉด ๋‹น์—ฐํ•œ ๊ฒฐ๊ณผ๋กœ 20, 110์ด ๋‚˜์˜จ๋‹ค. 

์œ„์˜ ์˜ˆ์ œ๋“ค ์ฒ˜๋Ÿผ ๊ฐœ๋ณ„์ ์ธ ๊ณ„์‚ฐ์ด ์ด๋ฃจ์–ด์ง€๊ฒŒ ๋œ๋‹ค. 

 

์ด์™€ ๋‹ค๋ฅด๊ฒŒ ๊ฒฐ๊ณผ๋ฅผ ๋ˆ„์ ํ•  ์ˆ˜๋Š” ์—†์„๊นŒ? ์— ๋Œ€ํ•œ ๋‹ต์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ํด๋กœ์ €์ด๋‹ค. 

 

 

 

Q) ๊ฒฐ๊ณผ๋ฅผ ๋ˆ„์ ํ•  ์ˆ˜๋Š” ์—†์„๊นŒ ? 

A1) ํด๋ž˜์Šค ์ด์šฉ 

class Averager():
    def __init__(self):
        self._series = []

    def __call__(self, v):
        self._series.append(v)
        print('class >>> {} / {}'.format(self._series, len(self._series)))
        return sum(self._series) / len(self._series)

์šฐ์„  Averager ํด๋ž˜์Šค๋Š” ์ˆซ์ž๋ฅผ ๋„ฃ์œผ๋ฉด ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ•˜์—ฌ ํ‰๊ท ์„ ๊ตฌํ•ด์ฃผ๋Š” ํด๋ž˜์Šค์ด๋‹ค. 

๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด _series ์— ๋นˆ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. 

์ €๋ฒˆ ๊ธ€์—์„œ ๋ฐฐ์šด __call__ ๋ฉ”์†Œ๋“œ๋Š” ๊ฐ์ฒด๋ฅผ ๋ฉ”์†Œ๋“œ ํ˜•ํƒœ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. 

 

# ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ 
avg_cls = Averager()

print('EX3-1 - ', avg_cls(15))
print('EX3-2 - ', avg_cls(35))
print('EX3-2 - ', avg_cls(40))

 class >>> [15] / 1 
 EX3-1 -  15.0 
 class >>> [15, 35] / 2 
 EX3-2 -  25.0 
 class >>> [15, 35, 40] / 3 
 EX3-2 -  30.0 

์ด๋ ‡๊ฒŒ ๋ˆ„์ ์œผ๋กœ ์ €์žฅํ•ด๋‘์—ˆ๋‹ค๊ฐ€ ํ‰๊ท ์„ ๊ตฌํ•ด์ค€๋‹ค. 

 

 

 

A2) ํด๋กœ์ € ์ด์šฉ 

์ด๋ฒˆ์—” ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด 

1. ์ „์—ญ๋ณ€์ˆ˜ ์‚ฌ์šฉ ๊ฐ์†Œ 

2. ๋””์ž์ธ ํŒจํ„ด ์ ์šฉ 

def closure_avg1():
    # Free Variable
    # ํด๋กœ์ € ์˜์—ญ
    series = []
    def averager(v):
        # ์—ฌ๊ธฐ์— series๊ฐ€ ์—†๋Š”๋ฐ ๊ณ„์† ์ฐธ์กฐํ•˜๊ณ  ์žˆ์Œ 
        # series = [] ์—ฌ๊ธฐ์— ์“ด๋‹ค๋ฉด ๊ณ„์† ์ดˆ๊ธฐํ™”๋œ ํ›„ append๋จ 
        series.append(v)
        print('def1 >>> {} / {}'.format(series, len(series)))
        return sum(series) / len(series)
    return averager # ํ•จ์ˆ˜ ์ž์ฒด๋ฅผ ๋ฆฌํ„ด averager() ์ด๊ฒŒ ์•„๋‹˜

 

ํด๋กœ์ € ์˜์—ญ์—์„œ series๋ฅผ ์„ ์–ธํ•œ ๊ฒƒ ๋นผ๊ณ ๋Š” ๋‹ค๋ฅธ ๊ฒŒ ์—†์–ด๋ณด์ธ๋‹ค. ์›๋ž˜ ํ•จ์ˆ˜์•ˆ์—์„œ ์„ ์–ธํ•œ ๋ณ€์ˆ˜๋Š” ํ•จ์ˆ˜ ๋ฆฌํ„ด๊ณผ ๋™์‹œ์— ์ดˆ๊ธฐํ™”๋œ๋‹ค. ํ•˜์ง€๋งŒ ํด๋กœ์ € ์˜์—ญ์—์„œ ์„ ์–ธํ•œ ๋ณ€์ˆ˜๋Š” ์ดˆ๊ธฐํ™” ๋˜์ง€ ์•Š์•„ ์ด๋Ÿฌํ•œ ๋ˆ„์ ์œผ๋กœ ์ถ”๊ฐ€๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์งค ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 

avg_closuer1 = closure_avg1()

print('EX4-1 - ', avg_closuer1(15))
print('EX4-1 - ', avg_closuer1(35))
print('EX4-1 - ', avg_closuer1(40))

์ง€๊ธˆ๋ณด๋‹ˆ ์˜คํƒ€๊ฐ€ ๋‚ฌ๋‹ค closuer ์ด๋ผ๊ณ  ๋˜์–ด์žˆ๋‹ค! 

def1 >>> [15] / 1
EX4-1 -  15.0
def1 >>> [15, 35] / 2
EX4-1 -  25.0
def1 >>> [15, 35, 40] / 3
EX4-1 -  30.0

๊ฒฐ๊ณผ๊ฐ€ ์ž˜ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

print('EX5-1 - ', dir(avg_closuer1))
print()
print('EX5-2 - ', dir(avg_closuer1.__code__))
print()
print('EX5-3- ', avg_closuer1.__code__.co_freevars)  # ํด๋กœ์ €์— ์ ‘๊ทผ
print()
print('EX5-4 - ', dir(avg_closuer1.__closure__[0]))  
print()
print('EX5-5 - ', dir(avg_closuer1.__closure__[0].cell_contents[1]))

EX5-1 -  ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

__code__ ์— ์ ‘๊ทผ
EX5-2 -  ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_kwonlyargcount', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
co_vars ์— ์ ‘๊ทผ ---> ํด๋กœ์ €์— ์ ‘๊ทผ 
EX5-3-  ('series',)
series๊ฐ€ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
EX5-4 -  ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']

EX5-5 -  ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', 
'__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

 

 

 

*** ์ž˜๋ชป๋œ ํด๋กœ์ € ์‚ฌ์šฉ ์˜ˆ 

def closure_avg2():
    # Free variable
    # ํด๋กœ์ € ์˜์—ญ 
    cnt = 0 
    total = 0 
    
    def averager(v):
        cnt += 1
        total += v 
        print('def2 >>> {} / {}'.format(total, cnt))
        return total / cnt 
    return averager

 Traceback (most recent call last): 
  File "c:/Users/./Desktop/python_high/chapter04_02.py", line 155, in <module>     
    print('EX5-5 - ', avg_closure2(15)) 
  File "c:/Users/./Desktop/python_high/chapter04_02.py", line 147, in averager     
    cnt += 1 
 UnboundLocalError: local variable 'cnt' referenced before assignment 

์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” UnboundLocalError๊ฐ€ ์‹คํ–‰๋œ๋‹ค. 

 

 

 

---> ํ•ด๊ฒฐ๋ฐฉ๋ฒ• 

def closure_avg2():
    # Free variable
    # ํด๋กœ์ € ์˜์—ญ 
    cnt = 0 
    total = 0 
    def averager(v):
        nonlocal cnt, total  
        cnt += 1
        total += v 
        print('def2 >>> {} / {}'.format(total, cnt))
        return total / cnt 
    return averager

<nonlocal ๋ณ€์ˆ˜๋ช…> ์„ ๋ถ™์—ฌ์ฃผ๋ฉด ํด๋กœ์ € ์˜์—ญ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. 

avg_closure2 = closure_avg2()

print('EX5-5 - ', avg_closure2(15))
print('EX5-5 - ', avg_closure2(35))
print('EX5-5 - ', avg_closure2(40))

 def2 >>> 15 / 1 
 EX5-5 -  15.0 
 def2 >>> 50 / 2 
 EX5-5 -  25.0 
 def2 >>> 90 / 3 
 EX5-5 -  30.0 

๊ทธ๋Ÿผ ๊ฒฐ๊ณผ ๊ฐ’์ด ์ž˜ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

- ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ , Decorator 

์žฅ์ 

1. ์ค‘๋ณต์ œ๊ฑฐ, ์ฝ”๋“œ ๊ฐ„๊ฒฐ 

2. ํด๋กœ์ €๋ณด๋‹ค ๋ฌธ๋ฒ• ๊ฐ„๊ฒฐ 

3. ์กฐํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•  ๋•Œ ์šฉ์ด 

 

๋‹จ์  

1. ๋””๋ฒ„๊น…์ด ์–ด๋ ค์›€ 

2. ์—๋Ÿฌ์˜ ๋ชจํ˜ธํ•จ 

 

import time 

def perf_clock(func): 
    def perf_clocked(*args):
        # ์‹œ์ž‘ ์‹œ๊ฐ„ 
        st = time.perf_counter()
        result = func(*args)
        # ์ข…๋ฃŒ ์‹œ๊ฐ„ 
        et = time.perf_counter() - st
        # ํ•จ์ˆ˜๋ช… 
        name = func.__name__ 
        # ๋งค๊ฐœ๋ณ€์ˆ˜ 
        arg_str = ','.join(repr(arg) for arg in args)
        # ์ถœ๋ ฅ 
        print('Result : [%0.5fs] %s(%s) -> %r' % (et, name, arg_str, result))
        return result
    return perf_clocked

์šฐ์„  perf_clock ์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ํ•จ์ˆ˜๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๊ทธ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„๊ณผ ๊ทธ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ด ์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. 

 

 

* ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๋ฏธ์‚ฌ์šฉ 

def time_func(seconds):
    time.sleep(seconds)


def sum_func(*numbers):
    return sum(numbers)


def fact_func(n):
    return 1 if n < 2 else n * fact_func(n-1)

์ด 3๊ฐ€์ง€์˜ ํ•จ์ˆ˜๋กœ ์‹คํ—˜์„ ํ•ด๋ณธ๋‹ค. time_func : 2์ดˆ sleep , sum_fun : ์ˆซ์ž ํ•ฉํ•˜๊ธฐ, fact_func : ํŒฉํ† ๋ฆฌ์–ผ ๊ณ„์‚ฐ 

non_deco1 = perf_clock(time_func)
non_deco2 = perf_clock(sum_func)
non_deco3 = perf_clock(fact_func)

print('EX7-1 - ', non_deco1, non_deco1.__code__.co_freevars)
print('EX7-2 - ', non_deco2, non_deco2.__code__.co_freevars)
print('EX7-3 - ', non_deco3, non_deco3.__code__.co_freevars)

print('*' * 40, 'Called Non Deco -> time_func')
print('EX7-4 - ')
non_deco1(2)
print('EX7-5 - ')
non_deco2(100, 200, 300, 500)
print('EX7-6 - ')
non_deco3(100)

EX7-1 -  <function perf_clock.<locals>.perf_clocked at 0x0000029029B70EA0> ('func',)   
EX7-2 -  <function perf_clock.<locals>.perf_clocked at 0x0000029029B70F28> ('func',)   
EX7-3 -  <function perf_clock.<locals>.perf_clocked at 0x0000029029B74048> ('func',)   
**************************************** Called Non Deco -> time_func

 EX7-4 - Result : [2.00830s] time_func(2) -> None 
 EX7-5 -  Result : [0.00001s] sum_func(100,200,300,500) -> 1100 
 EX7-6 - Result : [0.00017s] fact_func(100) ->   93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 

perf_clock์˜ ์ธ์ž๋กœ ๊ฐ ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ด์ค€๋‹ค. ๊ทธ ๋‹ค์Œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด , ์›ํ•˜๋˜ ๊ฒฐ๊ณผ๊ฐ€ ์ž˜ ๋‚˜์˜จ๋‹ค! 

 

 

 

 

* ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ์‚ฌ์šฉ 

@perf_clock
def time_func(seconds):
    time.sleep(seconds)


@perf_clock
def sum_func(*numbers):
    return sum(numbers)


@perf_clock
def fact_func(n):
    return 1 if n < 2 else n * fact_func(n-1)

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ•จ์ˆ˜ ์œ„์— @perf_clock ์„ ์ž‘์„ฑํ•œ๋‹ค. 

print('*' * 40, 'Called Deco -> time_func')
print('EX7-7 - ')
time_func(2)

print('*' * 40, 'Called Deco -> sum_func')
print('EX7-7 - ')
sum_func(10, 20, 30, 40, 50)

print('*' * 40, 'Called Deco -> fact_func')
print('EX7-7 - ')
fact_func(5)

**************************************** Called Deco -> time_func 
EX7-7 -
Result : [2.01093s] time_func(2) -> None 
**************************************** Called Deco -> sum_func 
EX7-7 -
Result : [0.00002s] sum_func(10,20,30,40,50) -> 150 
**************************************** Called Deco -> fact_func 
EX7-7 -
Result : [0.00000s] fact_func(1) -> 1 
Result : [0.00026s] fact_func(2) -> 2 
Result : [0.00058s] fact_func(3) -> 6 
Result : [0.00087s] fact_func(4) -> 24 
Result : [0.00110s] fact_func(5) -> 120 

๊ทธ๋Ÿผ ์ด๋ ‡๊ฒŒ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์ง€ ์•Š์•„๋„ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ)

 

<์ด์ „ ๊ธ€>

https://silvercoding.tistory.com/24

 

[python ์‹ฌํ™”] 7. ํ•ด์‹œํ…Œ์ด๋ธ”(hashtable), Dictionary, Set ์‹ฌํ™”

์ฝ”๋“œ - ํŒจ์บ  ์ˆ˜์—… ์ฝ”๋“œ ์ฐธ๊ณ  (ํŒจ์บ  ์ˆ˜์—… ์ •๋ฆฌ) <์ด์ „ ๊ธ€> https://silvercoding.tistory.com/23 https://silvercoding.tistory.com/22 https://silvercoding.tistory.com/21 https://silvercoding.tistory.com/20..

silvercoding.tistory.com

 

 

 

์˜ˆ์ „ ๊ธ€์—์„œ๋„ ๋‹ค๋ฃจ์—ˆ๋“ฏ์ด ํŒŒ์ด์ฌ์˜ ๋ชจ๋“  ๊ฒƒ์€ ๊ฐ์ฒด ๋ผ๋Š” ๊ฐœ๋…์€ ์•„์ฃผ ์ค‘์š”ํ•œ ๊ฐœ๋…์ด์—ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ•จ์ˆ˜ ๋˜ํ•œ ๊ฐ์ฒด๋ผ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. 

 

์ผ๊ธ‰ํ•จ์ˆ˜(์ผ๊ธ‰ ๊ฐ์ฒด) - ํŒŒ์ด์ฌ ํ•จ์ˆ˜์˜ ํŠน์ง• 

1. ๋Ÿฐํƒ€์ž„ ์ดˆ๊ธฐํ™” ๊ฐ€๋Šฅ 

2. ๋ณ€์ˆ˜์— ํ• ๋‹น ๊ฐ€๋Šฅ 

3. ํ•จ์ˆ˜ ์ธ์ˆ˜์— ์ „๋‹ฌ ๊ฐ€๋Šฅ (ex) sorted(keys=len) --- ํ•จ์ˆ˜ ์•ˆ์— ํ•จ์ˆ˜ 

4. ํ•จ์ˆ˜ ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜ ๊ฐ€๋Šฅ (ex) return function  

 

 

 

 

- ํŒฉํ† ๋ฆฌ์–ผ ํ•จ์ˆ˜ ๊ตฌํ˜„ ์˜ˆ์ œ 

def factorial(n):
    print("run")
    '''Factorial Function -> n:int'''
    if n ==1: # n < 2 
        return 1 
    return n * factorial(n-1)
    
    
class A: 
    pass 

์œ„์—์„œ ๋ณด์•˜๋˜ ์ผ๊ธ‰ํ•จ์ˆ˜์˜ ํŠน์ง• ์ค‘ 4๋ฒˆ์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค. ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋กœ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์„œ ํŒฉํ† ๋ฆฌ์–ผ์„ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ด๋‹ค. 

 

Aํด๋ž˜์Šค๋Š” ํ•จ์ˆ˜์™€ ๋น„๊ตํ•ด ๋ณด๊ธฐ ์œ„ํ•ด์„œ ์ƒ์„ฑํ•œ ๊ฒƒ . 

 

 

 

* ์‚ฌ์šฉํ•ด๋ณด๊ธฐ

print('EX1-1 - ', factorial(5))
print('EX1-2 - ', factorial.__doc__)
print('EX1-3 - ', type(factorial), type(A))
print('EX1-4 - ', set(sorted(dir(factorial)))-set(sorted(dir(A)))) # ํด๋ž˜์Šค์™€ ๋‹ค๋ฅด๊ฒŒ ํ•จ์ˆ˜๊ฐ€ ๊ฐ–๊ณ ์žˆ๋Š” ๋ฉ”์†Œ๋“œ๋“ค
print('EX1-5 - ', factorial.__name__) # ํ•จ์ˆ˜ ์ด๋ฆ„ 
print('EX1-6 - ', factorial.__code__) # ํ•จ์ˆ˜ ์ฝ”๋“œ ์œ„์น˜ 

EX1-1 ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด factorial(5) ๋ฅผ ํ•˜๋ฉด run์ด 5๋ฒˆ ํ˜ธ์ถœ ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

* ๋ณ€์ˆ˜ ํ• ๋‹น / ํ•จ์ˆ˜ ์ธ์ž ์ „๋‹ฌ

val_func = factorial
print('EX2-1 - ', val_func)
print('EX2-2 - ', val_func(5))
print('EX2-3 - ', map(val_func, range(1, 6)))
print('EX2-4 - ', list(map(val_func, range(1, 6))))

์ผ๊ธ‰ํ•จ์ˆ˜์˜ ํŠน์ง• 2๋ฒˆ๊ณผ ๊ฐ™์ด ๋ณ€์ˆ˜์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ณ€์ˆ˜์— ํ•จ์ˆ˜๋ฅผ ๋„ฃ๊ณ , ๊ธฐ์กด ๋งŒ๋“ค์–ด ๋†“์•˜๋˜ ํ•จ์ˆ˜์™€ ๋˜‘๊ฐ™์ด ์‚ฌ์šฉํ•ด ์ฃผ๋ฉด ๋œ๋‹ค. EX2-3, 4 ์—์„œ๋Š” ํŠน์ง• 3๋ฒˆ๊ณผ ๊ฐ™์ด mapํ•จ์ˆ˜์˜ ์ธ์ž์— factorial ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด ์‚ฌ์šฉํ•œ ๊ฒƒ์ด๋‹ค.

EX2-4๋Š” ์œ„์™€๊ฐ™์ด ๋ฆฌ์ŠคํŠธ๋กœ ๊ฒฐ๊ณผ ๊ฐ’์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

# ํ•จ์ˆ˜ ์ธ์ˆ˜ ์ „๋‹ฌ ๋ฐ ํ•จ์ˆ˜๋กœ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜ -> ๊ณ ์œ„ ํ•จ์ˆ˜ (Higher-order Function)
print('EX3-1 - ', list(map(val_func, filter(lambda x: x%2, range(1, 6))))) # --> ํ•จ์ˆ˜ ์•ˆ์— ํ•จ์ˆ˜ ์ „๋‹ฌ 
print('EX3-2 - ', [val_func(i) for i in range(1, 6) if i % 2])

EX2-4 ์—์„œ ๋” ๋‚˜์•„๊ฐ€ 1-6 ์ค‘์—์„œ ํ™€์ˆ˜์ธ ์ˆซ์ž๋“ค๋งŒ factorial์„ ์ ์šฉ์‹œํ‚ค๋Š” ์ฝ”๋“œ์ด๋‹ค. 

EX3-1๊ณผ EX3-2 ๋Š” ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋Š” ์ฝ”๋“œ์ด์ง€๋งŒ, EX3-2๋Š” list comprehension์„ ์‚ฌ์šฉํ•˜์˜€๊ณ , EX3-1์€ ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋กœ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•œ๋‹ค๋Š” ์ ์—์„œ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค. 

 

 

 

 

- reduce 

from functools import reduce
import functools
from operator import add

print('EX3-3 - ', reduce(add, range(1, 11))) # ๋ˆ„์  
print('EX3-4 - ', sum(range(1, 11)))

1๋ถ€ํ„ฐ 10๊นŒ์ง€ ๋”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์งœ์•ผํ•œ๋‹ค๊ณ  ํ•˜๋ฉด EX3-4 ์ฒ˜๋Ÿผ sumํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์งœ๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค. ์ด ๋ฐฉ๋ฒ• ๋ง๊ณ ๋„ functools์˜ reduce๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. 1๋ถ€ํ„ฐ 11๊นŒ์ง€ ์ฐจ๋ก€๋Œ€๋กœ ๋”ํ•ด๊ฐ€๋ฉฐ ์ค„์—ฌ๋‚˜๊ฐ€๋Š” ๋ฐฉ์‹์ด๋‹ค. 

 

 

* ์ต๋ช…ํ•จ์ˆ˜ (lambda) ์™€ reduce 

*** ์ต๋ช…ํ•จ์ˆ˜ (lambda) 

1. ๊ฐ€๊ธ‰์  ์ฃผ์„ ์‚ฌ์šฉ (๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ) 

2. ๊ฐ€๊ธ‰์  ํ•จ์ˆ˜ ์‚ฌ์šฉ 

3. ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜•ํƒœ๋กœ ๋ฆฌํŒฉํ† ๋ง ๊ถŒ์žฅ 

print('EX3-5 - ', reduce(lambda x, t: x + t, range(1, 11)))

์œ„์—์„œ์˜ addํ•จ์ˆ˜ ๋Œ€์‹  lambdaํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 1 + 2 ---> 3 + 3 ---> 6 + 4 ---> 10 + 5 ์ด๋Ÿฐ ์‹์œผ๋กœ ๋”ํ•ด์ง„ ๊ฐ’์— ๋ˆ„์ ์œผ๋กœ ๋‹ค์Œ ์ˆ˜๋ฅผ ๋”ํ•ด์ฃผ๋Š” ์›๋ฆฌ์ด๋‹ค. 

 

 

<lambda, map(), reduce(), filter() ์ฐธ๊ณ >

https://wikidocs.net/64

 

์œ„ํ‚ค๋…์Šค

์˜จ๋ผ์ธ ์ฑ…์„ ์ œ์ž‘ ๊ณต์œ ํ•˜๋Š” ํ”Œ๋žซํผ ์„œ๋น„์Šค

wikidocs.net

์–ด๋ ค์›€์„ ๋Š๋‚„ ๋• ์˜ˆ์‹œ๋ฅผ ๋ณด๊ณ  ์˜ค๊ธฐ! 

 

 

 

 

- Callable : ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž 

* ๋ฉ”์†Œ๋“œ ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธ 

---- ๋กœ๋˜ ์ถ”์ฒจ ํด๋ž˜์Šค ์˜ˆ์ œ ----

* ํด๋ž˜์Šค ์„ ์–ธ 

import random

class LottoGame:
    def __init__(self):
        self._balls = [n for n in range(1, 46)]

    def pick(self):
        random.shuffle(self._balls)
        return sorted([random.choice(self._balls) for n in range(6)])

์šฐ์„  random์„ import ํ•ด์ค€๋‹ค. ๊ฐ์ฒด๋ฅผ ์ดˆ๊ธฐ ์ƒ์„ฑํ–ˆ์„ ๋•Œ _balls์—๋Š” 1๋ถ€ํ„ฐ 45๊นŒ์ง€์˜ ์ˆซ์ž๋ฅผ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค. 

pick ํ•จ์ˆ˜์—์„œ๋Š” random.shuffle์„ ์‚ฌ์šฉํ•˜์—ฌ _balls๋ฅผ ์„ž์–ด ์ค€๋‹ค. ๊ทธ๋‹ค์Œ 6๊ฐœ๋ฅผ ๋ฝ‘์•„์ค€๋‹ค. 

 

 

* ๊ฐ์ฒด ์ƒ์„ฑ 

game = LottoGame()

 

 

* ๋กœ๋˜์ถ”์ฒจ ์‹คํ–‰ 

print('EX4-2 - ', game.pick())

 EX4-2 -  [1, 5, 14, 24, 30, 34] 

์ด๋ ‡๊ฒŒ 6๊ฐœ๊ฐ€ ์ž˜ ๋ฝ‘ํžˆ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. 

 

--- callable ์‚ฌ์šฉ 

print('EX4-1 - ', callable(str), callable(list), callable(factorial), callable(3.14), callable(game))

์œ„์—์„œ ๋งํ–ˆ๋“ฏ์ด callable์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์†ŒํŠธ ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค. 

 EX4-1 -  True True True False False 

str, list, factorial์€ ๋ชจ๋‘ ๋ฉ”์†Œ๋“œ ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์‹ค์ˆ˜์ธ 3.14 ๋˜๋Š” ๊ฐ์ฒด๊ฐ€ ๋“ค์–ด๊ฐ€ ์žˆ๋Š” ๋ณ€์ˆ˜์ธ game ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ๋ฉ”์†Œ๋“œ ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ์ด ๋ถˆ๊ฐ€๋Šฅ ํ•˜๋‹ค. 3.14(), game() <--- ์ด์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์†Œ๋ฆฌ์ด๋‹ค. 

 

 

ํ•˜์ง€๋งŒ ํด๋ž˜์Šค์—์„œ __call__๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด game๊ฐ™์€ ๊ฐ์ฒด๊ฐ€ ๋‹ด๊ธด ๋ณ€์ˆ˜๋Š” ๋ฉ”์†Œ๋“œ ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. 

 

--- __call__ ๋ฉ”์†Œ๋“œ ์‚ฌ์šฉํ•˜๊ธฐ (๋งค์šฐ ์ค‘์š”ํ•œ ๊ฐœ๋…์ž„) 

 

 

class LottoGame:

    ...

    def __call__(self):
        return self.pick()

LottoGame ํด๋ž˜์Šค์— __call__๋ฉ”์†Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค. self.pick์„ return ํ•ด์ฃผ๋Š” ๊ฒƒ์œผ๋กœ ์ž‘์„ฑํ•˜์˜€์œผ๋ฏ€๋กœ, game()์„ ํ˜ธ์ถœํ•˜๋ฉด pick ์ด ์‹คํ–‰๋  ๊ฒƒ์ด๋‹ค. 

 

*** ์‚ฌ์šฉํ•ด๋ณด๊ธฐ 

print('EX4-3 - ', game())
print('EX4-4 - ', callable(game))

 EX4-3 -  [14, 18, 42, 44, 44, 45] 
 EX4-4 -  True 

 

 

 

 

 

-- ๋งค๊ฐœ๋ณ€์ˆ˜ ์ž…๋ ฅ (*args, **kwargs) 

def args_test(name, *contents, point=None, **attrs):
    return '<args_test> -> ({}) ({}) ({}) ({})'.format(name, contents, point, attrs)

๋ณผ ๋•Œ๋งˆ๋‹ค ํ—ท๊ฐˆ๋ ธ๋˜ ๋ณ„ํ‘œ! ํ•จ์ˆ˜์˜ ์ธ์ž์— ๋ณ„ ํ•˜๋‚˜ (*) ๊ฐ€ ๋ถ™์œผ๋ฉด ํŠœํ”Œ์„ ๋ฐ›๊ณ , ๋ณ„ ๋‘๊ฐœ (**) ๊ฐ€ ๋ถ™์œผ๋ฉด ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ๋ฐ›๋Š”๋‹ค. 

ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด ์ผ๋ฐ˜ ๋ณ€์ˆ˜ name, ํŠœํ”Œ์„ ๋ฐ›๋Š” contents, default ๊ฐ’์ด ์ •ํ•ด์ ธ ์žˆ๋Š” point, ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ๋ฐ›๋Š” attrs, ์ด 4๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐ›๋Š” ํ•จ์ˆ˜ args_test๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค. 

 

print('EX5-1 - ', args_test('test1'))
print('EX5-2 - ', args_test('test1', 'test2'))
print('EX5-3 - ', args_test('test1', 'test2', 'test3', id='admin'))
print('EX5-4 - ', args_test('test1', 'test2', 'test3', id='admin', point=7))
print('EX5-4 - ', args_test('test1', 'test2', 'test3', id='admin', point=7, password='1234'))

* ํ•˜๋‚˜์”ฉ ํ’€์–ด์„œ ์ •๋ฆฌ 

 EX5-1 -  <args_test> -> (test1) (()) (None) ({}) 

'test1' ํ•˜๋‚˜๋ฅผ ๋„ฃ์—ˆ๋”๋‹ˆ name์— ๋“ค์–ด ๊ฐ”๋‹ค. 

 EX5-2 -  <args_test> -> (test1) (('test2',)) (None) ({}) 

'test1', 'test2' ๋ฅผ ๋„ฃ์—ˆ๋”๋‹ˆ name, contents ํŠœํ”Œ์— ๋“ค์–ด๊ฐ”๋‹ค. (default๊ฐ’์ด ์žˆ๋Š” point๋Š” point๋ฅผ ๋ช…์‹œํ•ด ์ฃผ์–ด์•ผ ํ•˜๋ฉฐ, attr์€ ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ๋ฐ›์œผ๋ฏ€๋กœ key, value๊ฐ’์„ ์ ์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.)  

 EX5-3 -  <args_test> -> (test1) (('test2', 'test3')) (None) ({'id': 'admin'}) 

'test1', 'test2', 'test3' ๋ฅผ ์—ฐ์†์ ์œผ๋กœ ์ ์–ด ์ฃผ์—ˆ๋”๋‹ˆ name์— test1, contents ํŠœํ”Œ์— test2, test3๊ฐ€ ๋“ค์–ด๊ฐ„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ฐจ๋ก€๋Œ€๋กœ ์ ๋”๋ผ๋„ point์—๋Š” ๋“ค์–ด๊ฐ€์ง€ ์•Š๋Š”๋‹ค. key์™€ value๋ฅผ ๋„ฃ์–ด์ฃผ๋‹ˆ attr ๋”•์…”๋„ˆ๋ฆฌ์— ๋“ค์–ด๊ฐ„ ๊ฒƒ ๋˜ํ•œ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 EX5-4 -  <args_test> -> (test1) (('test2', 'test3')) (7) ({'id': 'admin'}) 

์ด๋ฒˆ์—๋Š” point๋ฅผ ๋ช…์‹œํ•ด์ฃผ์–ด ๊ฐ’์„ ๋„ฃ์—ˆ๋”๋‹ˆ ์ž˜ ๋“ค์–ด ๊ฐ€ ์žˆ๋‹ค. 

 EX5-4 -  <args_test> -> (test1) (('test2', 'test3')) (7) ({'id': 'admin', 'password': '1234'}) 

์ˆœ์„œ์™€ ์ƒ๊ด€ ์—†์ด key, value ๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋”•์…”๋„ˆ๋ฆฌ์— ๋“ค์–ด ๊ฐ€ ์žˆ๋‹ค. 

 

 

 

- ํ•จ์ˆ˜ Signature

: ํ•จ์ˆ˜์˜ ์ธ์ž์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค ํ˜•ํƒœ์˜ ๋ฉ”์†Œ๋“œ 

from inspect import signature

 

์šฐ์„  inspect์˜ signature๋ฅผ import ํ•ด์ค€๋‹ค. 

 

sg = signature(args_test)

print('EX6-1 - ', sg)
print('EX6-2 - ', sg.parameters)

 EX6-1 -  (name, *contents, point=None, **attrs) 
 EX6-2 -  OrderedDict([('name', <Parameter "name">), ('contents', <Parameter "*contents">), ('point', <Parameter "point=None">), ('attrs', <Parameter "**attrs">)]) 

์œ„์™€ ๊ฐ™์ด ํ•จ์ˆ˜์˜ ์ธ์ž์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

* ์ธ์ž์˜ ๋ชจ๋“  ์ •๋ณด ์ถœ๋ ฅํ•ด๋ณด๊ธฐ 

# ๋ชจ๋“  ์ •๋ณด ์ถœ๋ ฅ 

for name, param in sg.parameters.items():
    print('EX6-3 - ', name, param.kind, param.default)

 

 EX6-3 -  name  POSITIONAL_OR_KEYWORD  <class 'inspect._empty'> 
 EX6-3 -  contents  VAR_POSITIONAL  <class 'inspect._empty'> 
 EX6-3 -  point  KEYWORD_ONLY  None 
 EX6-3 -  attrs  VAR_KEYWORD  <class 'inspect._empty'> 

 

 

 

 

- partial 

1. ์ฃผ๋กœ ํŠน์ • ์ธ์ˆ˜๋ฅผ ๊ณ ์ •ํ•œ ํ›„ ์ฝœ๋ฐฑํ•จ์ˆ˜์— ์‚ฌ์šฉ

2. ํ•˜๋‚˜ ์ด์ƒ์˜ ์ธ์ˆ˜๊ฐ€ ์ด๋ฏธ ํ• ๋‹น๋œ ํ•จ์ˆ˜์˜ ์ƒˆ ๋ฒ„์ „(์ƒˆ ๋ฒ„์ „์˜ ํ•จ์ˆ˜) ๋ฐ˜ํ™˜ 

3. ํ•จ์ˆ˜์˜ ์ƒˆ ๊ฐ์ฒด ํƒ€์ž…์€ ์ด์ „ํ•จ์ˆ˜์˜ ์ž์ฒด๋ฅผ ๊ธฐ์ˆ ํ•˜๊ณ  ์žˆ์Œ 

 

๊ธ€๋กœ ์ฝ์œผ๋ฉด ์ดํ•ด๊ฐ€ ์ž˜ ๊ฐ€์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. ์‚ฌ์šฉํ•ด ๋ณด์ž! 

from functools import partial

์šฐ์„  functools์˜ partial์„ import ํ•ด์ค€๋‹ค. 

 

 

*** cf ) mul ํ•จ์ˆ˜๋Š” ์™œ ์žˆ๋‚˜ 

from operator import mul 

print('EX7-1 - ', mul(10, 100))

์œ„ ์ฝ”๋“œ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” 10 * 100 ์„ ํ•˜๋ฉด ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌํ…๋ฐ, ๊ตณ์ด mul๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๊ฐ€ ์กด์žฌํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€. 

---> mul๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

 

 

* ์ธ์ˆ˜ ๊ณ ์ • 

five = partial(mul, 5)

์ด๋ ‡๊ฒŒ partialํ•จ์ˆ˜์˜ ์ธ์ž์— mulํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ฃผ๊ธฐ ์œ„ํ•œ ์šฉ๋„๋กœ ์“ฐ์ผ ์ˆ˜ ์žˆ๋‹ค. 

 

๊ทธ๋ž˜์„œ partial ํ•จ์ˆ˜๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€! 

์ธ์ˆ˜๋ฅผ ๊ณ ์ •์‹œ์ผœ ๋†“๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. partial(mul, 5) ๋Š” mul(5) <--- ์ด ์ƒํƒœ๋กœ 5๋ฅผ ๊ณ ์ •์‹œ์ผœ ๋†“๊ฒ ๋‹ค๋Š” ์†Œ๋ฆฌ์ด๋‹ค. 

 

 

* ๊ณ ์ • ์ถ”๊ฐ€ 

six = partial(five, 6)

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด mul(5, 6) <--- ์ด ์ƒํƒœ๋กœ ๊ณ ์ •์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค. 

 

* ์‚ฌ์šฉ

print('EX7-2 - ', five(100)) # ํ•œ๊ฐœ๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ 
# print(six(100)) # ---> ์˜ค๋ฅ˜ ๋‚จ . ์•„๋ฌด๊ฒƒ๋„ ๋ฐ›์„ ์ˆ˜ ์—†์Œ 
print('EX7-3 - ', six())
print('EX7-4 - ', [five(i) for i in range(1, 11)])
print('EX7-5 - ', list(map(five, range(1, 11)))) 

EX7-4, 5 ์™€ ๊ฐ™์ด 5์— 1~10์˜ ์ˆซ์ž๋ฅผ ๊ณฑํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•œ ์ƒํ™ฉ์—์„œ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ์งค ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

 

+ Recent posts