while (1): study();

Part3. 객체로서의 함수 본문

독서

Part3. 객체로서의 함수

전국민실업화 2021. 12. 5. 05:06
728x90

5. 일급 함수

일급 객체

1. 런타임에 생성 가능

2. 데이터 구조체의 변수나 요소에 할당 가능

3. 함수 인수로 전달 가능

4. 함수 결과로 반환 가능

 

고위 함수(higher-order function): 함수를 결과로 반환하는 함수

map(), filter() -> 컴프리헨션의 등장으로 중요성 저하

reduce()

all(): 모든 iterable이 참이면 true

any(): iterable이 하나라도 참이면 true

 

람다: 최대한 안 쓰는게 좋음 (가독성)

 

매개변수

*을 기점으로 위치 매개변수와 키워드 매개변수를 나눔

def f(a, *, b): # b는 기본값이 지정되지 않은 키워드 매개변수
	return a, b

* 매개변수 추출: inspect 이용

from inspect import signature

sig = signature(func)
for name, param in sig.parameters.items():
	print(param.kind, ':', name, '=', param.default)

 

함수 애너테이션

전혀 처리하지 않음, 인터프리터에 아무 의미 없음

독스트링과 같이 주석을 달아주는 것뿐

 

함수형 프로그래밍 모듈

1) operator: reduce 등에 쓸 수 있는 연산함수 지원

itemgetter(), attrgetter()

from collections import namedtuple
from operator import attrgetter

LatLong = namedtuple('LatLong', 'lat long')
Metropolis = namedtuple('Metropolis', 'name cc pop coord')
metro_areas = [Metropolis(name, cc, pop, LatLong(lat, long)) for name, cc, pop, (lat, long) in metro_data]

name_lat = attrgetter('name', 'coord.lat')
for city in sorted(metro_areas, key=attrgetter('coord.lat')):
    print(name_lat(city))

2) functools

partial(): 함수 인수를 부분적으로 고정

from operator import mul, floordiv
from functools import partial

triple = partial(floordiv, 3)
list(map(triple, range(1, 10)))

 

6. 일급 함수 디자인 패턴

전략

콘텍스트: 일부 계산을 전략 컴포넌트에 위임

전략: 여러 전략이 구현된 공통 인터페이스

* abc.abstractmethod를 상속(플라이웨이트) or 함수를 전달(내부 상태없이 처리만 하는 경우)

* 최적 전략 선택

# 1. globals(): 전역 심볼 테이블 반환
[globals()[name] for name in globals()]

# 2. inspect.getmembers
[func for name, func in inspect.getmembers(module, inspect.is_function)]

 

명령

연산 실행 객체(Invoker)와 구현 객체(Receiver)를 분리

 

7. 함수 데커레이터와 클로저

데커레이터

1) 데커레이터는 데커레이트된 함수를 다른 함수로 대체

2) 임포트 타임에 실행(먼저 대체된 함수를 만들어놓음)

 

변수 범위 규칙

지역 변수 -> 전역 변수 순으로 찾으나

전역 변수와 같은 이름의 지역 변수가 컨텍스트 안에 선언되어 있으면 무조건 지역 변수로 판단

전역 변수로 만들고 싶으면 global 사용

 

클로저

 

def make_averager():
	series = [] # 자유변수
    
    def averager(new_value): # 클로저
    	series.append(new_value)
        total = sum(series)
        return total / len(series)
        
       return averager

함수 본체에서 정의하지 않고 참조하는 비전역 변수를 포함한 확장 범위를 가진 함수

함수를 정의할 때 존재하던 자유변수에 대한 바인딩을 유지하는 함수

함수가 다른 함수 안에 정의된 경우만 발생

자유변수에 새로운 값을 할당할때는 nonlocal 선언 필요 (+= 등 사용 시 지역변수로 판단해버리기 때문)

def make_averager():
    count, total = 0, 0
    
    def averager(new_value):
        nonlocal count, total
        count += 1
        total += new_value
        return total / count
    return averager

 

표준 라이브러리 데커레이터

functools.lru_cache(): 메모이제이션

@functools.lru_cache(maxsize=128)
@clock
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n - 2) + fibonacci(n - 1)

if __name__ == '__main__':
    print(fibonacci(6))

functools.singledispatch(): 첫번째 인수의 자료형에 따른 서로 다른 방식의 연산

import html
import numbers
from collections import abc

@functools.singledispatch
def htmlize(obj):
    content = html.escape(repr(obj))
    return '<pre>{}<pre>'.format(content)

@htmlize.register(str)
def _(text):
    content = html.escape(text).replace('\n', '<br>\n')
    return '<p>0<p>'.format(content)

@htmlize.register(numbers.Integral)
def _(n):
    return '<pre>{0} (0x{0:x})</pre>'.format(n)

@htmlize.register(tuple)
@htmlize.register(abc.MutableSequence)
def _(seq):
    inner = '</li>\n</li>'.join(htmlize(item) for item in seq)
    return '<ul>\n<li>' + inner + '</li>\n</ul>'

 

매개변수화된 데커레이터

인수를 받아 데커레이터를 반환하는 데커레이터 팩토리를 만들고, 데커레이트될 함수에 데커레이터 팩토리 적용

registry = set()

def register(active=True):
    def decorate(func):
        print('running register(active=%s) -> decorate(%s)' % (active, func))
        if active:
            registry.add(func)
        else:
            registry.discard(func)
        return func
    return decorate

@register(active=False)
def f1():
    print('running f1()')
    
@register(active=True)
def f2():
    print('running f2()')
    
def f3():
    print('running f3()')
728x90

'독서' 카테고리의 다른 글

Part5. 제어 흐름  (0) 2021.12.08
Part4. 객체지향 상용구  (0) 2021.12.05
Part2. 데이터 구조체  (0) 2021.12.05
Part1. 들어가며  (0) 2021.12.05
Ch8. 어텐션  (0) 2021.08.01
Comments