일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 파이썬
- Generator
- Python
- Substring with Concatenation of All Words
- 프로그래머스
- Python Implementation
- shiba
- 715. Range Module
- 컴퓨터의 구조
- 밴픽
- 315. Count of Smaller Numbers After Self
- 43. Multiply Strings
- Protocol
- Convert Sorted List to Binary Search Tree
- 109. Convert Sorted List to Binary Search Tree
- attribute
- Python Code
- LeetCode
- iterator
- Regular Expression
- kaggle
- 시바견
- Decorator
- data science
- 운영체제
- t1
- Class
- 30. Substring with Concatenation of All Words
- DWG
- concurrency
- Today
- Total
Scribbling
Python: Decorator & Closure 본문
Decorator is a callable that takes another function as its parameter. Decorator is executed during 'import time'.
The key idea about closure you must understand is that it can access to 'nonlocal' variables outside the function.
Take a look at the below exmaple.
def make_averager():
series = []
def averager(new_val):
series.append(new_val)
return sum(series) / len(series)
return averager
avg = make_averager()
avg(10)
avg(11)
print(avg(12))
Binding between freevars and closures are kept until the end.
print(avg.__code__.co_freevars)
print(avg.__closure__)
"Nonlocal" keyword is to define free variable. In the previous example, "series" was automatically interpreted as free variable as it is mutable data type. On the other hand, nonlocal keyword should be used in closure when dealing with immutable data types.
def make_averager():
count = 0
total = 0
def averager(new_val):
nonlocal count, total
count += 1
total += new_val
return total / count
return averager
avg = make_averager()
avg(10)
avg(11)
print(avg(12))
Now, back to decorator. Usually, we call a function in decorator. Below is the typical code format.
import time
import functools
def clock(func):
@functools.wraps(func)
def clocked(*args, **kwargs):
t0 = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - t0
print(f"{func.__name__} took {elapsed:1.3f} seconds and returned {result!r}")
return result
return clocked
@clock
def iamfunc(iamparam:str)->str:
'''
iamfunc
'''
return iamparam + 'was passed'
iamfunc('what happend?')
@functools.wraps(func)
From above, what is this for? This is to maintain original function's properties as below.
print(iamfunc.__name__)
print(iamfunc.__doc__)
Without it, iamfunc.__name__ and iamfunc.__doc__ would have been replaced with clocked function's properties.
import time
def clock(func):
def clocked(*args, **kwargs):
t0 = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - t0
print(f"{func.__name__} took {elapsed:1.3f} seconds and returned {result!r}")
return result
return clocked
Decorators in STL
These three decorators are for class. For details, refer to below link.
@property # for setter / getter method
@classmethod # to define class method
@staticmethod # to define static method
https://focalpoint.tistory.com/283
functools.lru_cache(maxsize, typed) is for memoization.
- if typed is set to True, seperate result will be stored for different data types. (i.e. 1 & 1.0)
- all params should be hashable.
import functools
@functools.lru_cache()
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(30))
Python doesn't provide function overloading. As a result, it feels more complicated to deal with different data types. functools.singleddispath() is to specialize a certain function.
from functools import singledispatch
from collections import abc
import numbers
@singledispatch
def iamfunc(iamparam):
print(f"Not specialized Function Says: {iamparam!r} has data type of {type(iamparam)}.")
@iamfunc.register(str)
def _(string):
print(f"Specialized Function Says: {string!r} has data type of str.")
@iamfunc.register(numbers.Integral)
def _(num):
print(f"Specialized Function Says: {num!r} has data type of int.")
@iamfunc.register(abc.MutableSequence)
@iamfunc.register(tuple)
def _(seq):
print(f"Specialized Function Says: {seq!r} has data type of seq.")
iamfunc([1, 2, 3])
iamfunc((4, 5))
iamfunc(3)
iamfunc(3.3)
iamfunc('hello world')
Notes:
- numbers.Inegral is abstract base class for int type.
- abc.MutableSequence is abstract base class for mutable sequence types.
For multiple decorators, they work like this.
@d1
@d2
def f():
print('f')
f = d1(d2(f))
Now, a little bit more trickier part: decorators with params. Here we call echo as decorator factory.
import functools
def ehco(times):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result * times
return wrapper
return decorator
@ehco(5)
def printer(text):
return text
print(printer('What?'))
print(printer.__name__)
'Computer Science > Python' 카테고리의 다른 글
Python: Pythonic Object (0) | 2022.04.05 |
---|---|
Python: Object References (0) | 2022.04.04 |
Python: Design Patterns (0) | 2022.03.25 |
Python: Memoryview function (0) | 2022.03.23 |
Python Immutable Dictionary, Set (0) | 2022.03.22 |