μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리)

 

<이전 κΈ€>

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