함수적 기법 (2)
참고자료: Functional Programming in Python (by. David Mertz)
0. 함수형 프로그래밍
- 파이썬은 순수한 functional paradigm 언어는 아니다.
- 하지만 파이썬은 다양한 방식의 프로그래밍을 지원하므로 어떤 것을 사용할지는 선택!
- 함수형 프로그래밍에서 연속된 실행은 합성함수로 한다.
1. Encapsulation을 하는 이유
- 재사용을 하기 위해서
- 함수로 만들면 다시 사용하고자 할 때 해당 함수를 호출하기만 하면 된다.
2. Comprehension
- 동시에 여러 개 만드는 것
속도가 빠르고 간결하다.
- list, set, dictionary는 conprehension으로 만들 수 있지만 튜플로는 만들 수 없다. (튜플 -> 제너레이터)
(1) list comprehension
a = [str(x) for x in range(10) if x%2==0]
# ['0', '2', '4', '6', '8']
a = [x+1 for x in range(10)]
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
(2) set comprehension
a = {x+1 for x in range(10)}
# {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}
(3) dictionary comprehensino
a = {x: x+1 for x in range(10)}
# {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
3. Generator
next() 사용 가능
(1) tuple을 통해 만드는 방식
a = (x for x in range(3))
next(a)
(2) yield를 통해 만드는 방식
def b():
# yield 1
# yield 2
yield from range(10)
t = b()
next(t)
4. Recursion
- 수학과 유사하기 때문에 수학식으로 표현될 수 있으면 Recursion을 사용할 수 있다.
- Recursion은 속도가 느리고 메모리를 차지하기 때문에 파이썬에서는 사용하지 않는 것이 좋다.
5. lambda
- 메모리에 올라가지 않는 휘발성이기 때문에 일회용으로 사용하기 위해 lambda를 사용함
b = lambda : 2
처럼 람다식을 할당할 수도 있고 할당하면 메모리에 남는다.
- 람다를 사용할 때와 일반적인 함수를 사용할 때의 속도 차이는 거의 없음
6. Callables
Callable이란?
- call: 함수를 호출
- callable: 함수처럼 괄호를 붙일 수 있는가? 여부
a = 1
callable(a) # False
Callable 유형
- Function 계열
def f(): return 1 callable(f) # True
- 객체 클래스를 인스턴스할 때
- __call__이 정의되어 있는 클래스의 인스턴스
First Class Function
- 값처럼 쓸 수 있음
a = [len, str] a[0]([1,2,3]) # 3
7. Lazy Evaluation
- iterator로 변신시키면 구현하기 쉽다.
- generator를 만들거나 generator 표현식(튜플 형태의 컴프리헨션)을 통해 할 수도 있다.
8. 데코레이터(@)
- 기존에 만들어졌던 함수의 기능을 추가하거나 변경할 때 사용할 수 있음
- 메소드에 데코레이터를 붙이면 괄호 없이 사용할 수 있음
데코레이터 기본 생성 규칙
- 맨 밖에 있는 함수(Wrapper)는 인자로 fucntion을 받아야 한다.
- 인자로 받은 function은 중첩된 함수 안에서 실행되어야 한다.
- 리턴은 함수로 리턴되어야 한다.
그러면 @이름
으로 바꿀 수 있다.
def foo(fn):
def inner():
print('About to call function.')
fn()
print('Finished calling function.')
return inner
# 여기에 있는 함수를 foo()에 집어넣는다.
@foo
def bar():
print('Calling function bar.')
bar()
# About to call function.
# Calling function bar.
# Finished calling function.
2중구조
- 인자를 몇 개를 받던지 범용적으로 적용되게 하기 위해
*t, **s
사용 - y.__name__하면 y가 아니라 inner가 나오기 때문에 기능을 변경시키기 위해 다시 decorator를 씀
- @wraps
from functools import wraps
def author(func):
@wraps(func)
def inner(*t, **s):
print('by author')
func(*t, **s)
return inner
@author
def y(t):
print(t)
y(3)
# by author
# 3
3중구조
- 조건을 하나 더 붙일 때 3중구조를 사용
if tt==7 ~
와 같이 사용할 수 있음def outer(tt): def wrapper(func): @wraps(func) def inner(*t, **s): func(*t, **s) print(tt) return inner return wrapper
@outer(tt=7) def y(t): print(t) y(3) # 3 # 7
여러 개의 데코레이터 사용
-
가까운 데코레이터(decorator2)부터 실행되고 그 반환값이 함수이면 다시 위에 있는 데코레이터(decorator1)를 실행하게 된다.
@decorator1 @decorator2 def ...
Leave a comment