μ½λ - ν¨μΊ μμ μ½λ μ°Έκ³ (ν¨μΊ μμ μ 리)
<μ΄μ κΈ>
https://silvercoding.tistory.com/25
μ΄λ² ν¬μ€νΈμμλ λ°μ½λ μ΄ν°λ₯Ό μμλ³Ό κ²μ΄λ€. λ°μ½λ μ΄ν°λ μ΄λ ΅λ€κ³ λλΌλ κ²μ΄ λΉμ°νλ€. λ°μ½λ μ΄ν°μ λ€μ΄κ°κΈ° μ μλ λ³μμ λ²μμ ν΄λ‘μ κ°λ μ μμμΌ νλ―λ‘ μ΄ λμ λ¨Όμ μ΄ν΄λ³΄μ.
- νμ΄μ¬ λ³μ λ²μ
*** μ μλ³μ vs μ§μλ³μ μ°Έκ³
μν€λ μ€
μ¨λΌμΈ μ± μ μ μ 곡μ νλ νλ«νΌ μλΉμ€
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
κ·ΈλΌ μ΄λ κ² λ³μλ₯Ό μμ±ν΄μ£Όμ§ μμλ κ°λ¨νκ² κ²°κ³Όλ₯Ό μ»μ μ μλ€.