지난 학기에 '인공지능'이라는 수업을 들었는데, 선생님께서 프롤로그라는 언어를 배우라고 강요하셨는데, 생각하는 방식이 전혀 달랐어요. 예전에 배웠는데 인생이 달라졌네요 오랫동안 하노이타워를 작성할까 고민하다가 결국 인터넷에서 코드를 발견해서 수정했습니다. 글을 쓰기 전에
hanoi(N) :- dohanoi(N, 'a', 'b', 'c'). dohanoi(0, _ , _ , _ ) :- !. dohanoi(N, A, B, C) :- N1 is N-1, dohanoi(N1, A, C, B), writeln([move, N, A-->C]), dohanoi(N1, B, A, C).
라는 문단을 올렸습니다. 당시에는 거의 이해가 되었지만 주된 이유는 정보가 너무 적고 디버깅이 불가능하기 때문입니다. . 버그를 만날 때마다 지금은 약간 어지러움을 느낍니다. 하지만 당시에는 프롤로그가 Lisp와 경쟁할 수 있었다고 하는데, 최근에는 Lisp에 조금 관심이 생겼습니다. 이런 일을 마치고 나면 이런 함수형 언어에 경의를 표하게 될 것입니다.
함수형 프로그래밍이란 무엇인가요? Liao Da는 다음과 같이 썼습니다.
함수형 프로그래밍은 순수 함수형 프로그래밍 언어로 작성된 함수에는 변수가 없습니다. 입력이 결정되면 출력이 결정됩니다. 이 함수를 부작용이 없는 순수 함수라고 부릅니다. 변수 사용을 허용하는 프로그래밍 언어에서는 함수 내부의 변수 상태가 불확실하기 때문에 같은 입력이라도 다른 출력이 나올 수 있기 때문에 이런 종류의 함수에는 부작용이 있습니다.
읽어도 이해가 안 될 수도 있으니 걱정하지 마세요. 먼저 이 섹션을 읽어보세요.
수학과 컴퓨터 과학에서 고차 함수는 다음 조건 중 하나 이상을 만족하는 함수입니다.
하나 이상의 함수를 입력으로 받아들이고
함수를 출력합니다
즉, 함수 자체를 매개변수로 전달합니다. 또는 함수를 반환합니다.
예를 들어 일반 할당처럼 변수에 함수를 할당할 수 있습니다.
>>> min(1, 2) 1 >>> f = min >>> f(1, 2) 1 >>> f <built-in function min> >>> min <built-in function min>
함수에 값을 할당할 수도 있습니다(코드 계속).
>>> min = 10 >>> min(1, 2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not callable >>> f(1, 2) 1 >>> min = f >>> min(1, 2) 1
예를 들어 모든 숫자의 합을 계산하는 함수와 같은 매개변수를 전달할 수도 있습니다.
>>> def add(a, b): ... return a+b ... >>> def mysum(f, *l): ... a = 0 ... for i in l: ... a = f(a, i) ... return a ... >>> mysum(add, 1, 2, 3) 6 >>> mysum(add, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 55
물론 이 f를 곱셈으로 바꾸는 것은 모든 숫자의 곱을 계산한다는 의미입니다.
파이썬에 내장되어 자주 사용되는 고차함수 몇 가지를 살펴보겠습니다.
지난 학기에 클라우드 컴퓨팅 강좌를 수강할 때 이 단어를 막연하게 들었던 기억이 있는데 수업이 너무 지루해서 잘 듣지 못했던 것 같습니다. 여기서 보면 이상하다고 생각해요. 너무 똑같나요? ?
그렇지만 각 기능의 역할에 대해 간단히 말씀드리자면 별로 할 말이 없습니다.
map의 경우 계산식은 다음과 같습니다.
map(f, [x1, x2, ..., xn]) = [f(x1), f(x2), ..., f(xn)]
Reduce의 경우 계산식은 다음과 같습니다.
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
Liao Da는 매우 명확하게 말했습니다. .
filter는 함수를 허용하고 iterable하고 목록을 반환한다는 점에서 map 함수와 유사하지만 함수 반환 값에 따라 값을 유지할지 여부를 결정하는 기능이 있습니다. 사실입니다. 예를 들면 다음과 같습니다.
def is_odd(n): return n % 2 == 1 list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) # 结果: [1, 5, 9, 15]
sorted 함수도 함수를 매개변수 키에 전달하면 정렬할 시퀀스를 키 함수를 통해 처리한 후 정렬할 수 있습니다. , 그러나 값은 변경되지 않습니다. 예:
>>> sorted([36, 5, -12, 9, -21], key=abs) [5, 9, -12, -21, 36]
익명 함수에 대해서는 자세히 살펴보겠습니다. 나중에 사용할 때 데코레이터에 대해 오랫동안 공부했던 기억이 나네요. 이번에 다시 복습해 보겠습니다.
첫 번째는 각 함수 호출 전에 로그를 인쇄하는 간단한 데코레이터입니다.
import logging def log(func): def wrapper(*args, **kw): logging.warn("%s is running" % func.__name__) func(*args, **kw) return wrapper
이것은 매우 간단한 데코레이터입니다. 사용하는 것은 어떻습니까? 그것? 내가 본 첫 번째 사용법은 장식해야 할 함수 앞에 @를 추가하는 것이었지만 실제로 이것은 Python의 구문 설탕입니다. 먼저 함수 f를 정의하는 것이 더 이해하기 쉽습니다. 이 정의 후에는 f 함수를 호출합니다.
def f(): print("in function f") f = log(f)
@log를 사용한 결과는 동일합니다. 실제로 @ 기호는 데코레이터의 구문 설탕 역할을 하며 이전 할당 문과 동일한 기능을 갖습니다. , 다음과 같은 또 다른 할당 작업을 피하여 코드를 더 간결하고 명확하게 만듭니다.
>>> f() WARNING:root:f is running in function f
매개변수가 있는 데코레이터
@log def f(): print("in function f")
추가 이해
import logging def log(level): def decorator(func): def wrapper(*args, **kw): logging.warn("%s is running at level %d" % (func.__name__, level)) return func(*args, **kw) return wrapper return decorator @log(2) def f(): print("in function f") >>> f() WARNING:root:f is running at level 2 in function f
첫 번째 데코레이터 할당문에 접속하면 무슨 일이 일어났는지 대략적으로 이해할 수 있습니다.
f는 log(로 수정된 반환 값을 가리킵니다. f) 즉, 래퍼 기능입니다. 원래 함수 f가 실행될 때마다 래퍼 함수가 호출됩니다. 이 예에서는 로그가 먼저 인쇄된 다음 원래 함수 f가 실행됩니다.f = log(f)
그러나 이로 인해 원래 함수 f의 메타 정보가 대체되고 f에 대한 많은 정보가 사라지는 문제가 발생하지만 다행히도 우리는 이를 가지고 있습니다. functools 모듈 수정 함수는 다음과 같습니다:
#对于不加装饰器的 f,其 name 不变 >>> def f(): ... print("in function f") ... >>> f.__name__ 'f' #对于添加装饰器的函数,其 name 改变了 >>> @log ... def f(): ... print("in function f") ... >>> f.__name__ 'wrapper'
또한 동일한 함수에 여러 데코레이터를 추가할 수 있습니다:
import functools import logging def log(func): functools.wraps(func) def wrapper(*args, **kw): logging.warn("%s is running" % func.__name__) func(*args, **kw) return wrapper >>> @log ... def f(): ... print("in function f") ... >>> f.__name__ 'f'
요약
"함수형 프로그래밍"과 관련된 더 많은 [파이썬] 기사를 보시려면 PHP 중국어 홈페이지를 주목해주세요!