>백엔드 개발 >파이썬 튜토리얼 >Python Advanced: 클로저 운반 상태

Python Advanced: 클로저 운반 상태

黄舟
黄舟원래의
2017-02-07 17:25:561177검색

클로저

파이썬에서는 함수도 객체입니다. 따라서 함수를 정의할 때 다른 중첩 함수를 정의하고 중첩 함수를 반환할 수 있습니다. 예:

from math import pow
def make_pow(n):
    def inner_func(x):     # 嵌套定义了 inner_func
        return pow(x, n)   # 注意这里引用了外部函数的 n
    return inner_func      # 返回 inner_func

위 코드에서 make_pow 함수는 내부 함수 inner_func를 정의한 다음 이 함수를 반환합니다. 따라서 make_pow를 사용하여 다른 함수를 생성할 수 있습니다:

>> > pow2 = make_pow(2)  # pow2 是一个函数,参数 2 是一个自由变量
>> > pow2
<function inner_func at 0x10271faa0 >
>> > pow2(6)
36.0

또한 내부 함수 inner_func가 외부 함수 make_pow의 자유 변수 n을 참조한다는 사실도 알아냈습니다. 이는 make_pow 함수의 수명 주기가 끝나면 다음을 의미합니다. 이후에도 변수 n은 inner_func에 의해 참조되는 inner_func에 계속 저장됩니다.

>> > del make_pow         # 删除 make_pow
>> > pow3 = make_pow(3)
Traceback(most recent call last):
    File "<stdin>", line 1, in < module >
NameError:
    name &#39;make_pow&#39; is not defined
>> > pow2(9)     # pow2 仍可正常调用,自由变量 2 仍保存在 pow2 中
81.0

---|---

위의 상황과 마찬가지로 함수는 외부 함수의 관련 매개변수와 변수를 참조하는 내부 함수를 반환합니다. 내부 함수를 클로저라고 합니다.

위의 예에서 inner_func는 자유 변수 n을 참조하는 클로저입니다.

클로저의 역할

  • 클로저의 가장 큰 특징은 클로저를 생성한 환경이 해제되어도 클로저가 여전히 존재한다는 점입니다. ;

  • 전달된 매개변수가 동일하더라도 클로저는 런타임에 여러 인스턴스를 가질 수 있습니다. 예:

>> > pow_a = make_pow(2)
>> > pow_b = make_pow(2)
>> > pow_a == pow_b
False
  • 클로저 패키지를 사용하면 클래스 인스턴스를 모의할 수도 있습니다.

여기서 클래스를 구성하여 한 지점에서 다른 지점까지의 거리를 알아보세요:

from math import sqrt
class Point(object):
    def __init__(self, x, y):
        self.x, self.y = x, y
    def get_distance(self, u, v):
        distance = sqrt((self.x - u) ** 2 + (self.y - v) ** 2)
        return distance
>> > pt = Point(7, 2)        # 创建一个点
>> > pt.get_distance(10, 6)  # 求到另一个点的距离
5.0

클로저를 사용하여 구현:

def point(x, y):
    def get_distance(u, v):
        return sqrt((x - u) ** 2 + (y - v) ** 2)
    return get_distance
>> > pt = point(7, 2)
>> > pt(10, 6)
5.0


보시다시피 결과는 동일하지만 클래스를 사용하는 것보다 클로저를 사용하는 것이 더 간결합니다.

일반적인 오해

클로저의 개념은 매우 간단하지만 구현 시 다음 예와 같이 오해가 발생하기 쉽습니다.

def count():
    funcs = []
    for i in [1, 2, 3]:
        def f():
            return i
        funcs.append(f)
    return funcs

이 예에서는 for 루프에서 함수가 생성되고 funcs에 저장됩니다. 이제 위 함수를 호출하면 반환 결과가 1, 2, 3이라고 생각할 수 있지만 실제로는 그렇지 않습니다.

>> > f1, f2, f3 = count()
>> > f1()
3
>> > f2()
3
>> > f3()
3

왜요? 그 이유는 위의 함수 f가 변수 i를 참조하지만 함수 f가 즉시 실행되지 않기 때문입니다. for 루프가 끝나면 변수 i의 값은 3이고, funcs의 함수가 참조하는 변수는 모두 3입니다. , 최종 결과는 모두 3입니다.

따라서 클로저에서 루프 변수나 나중에 변경되는 변수를 참조하지 않도록 노력해야 합니다.

위 상황을 어떻게 해결하나요? 다음과 같이 다른 함수를 만들고 루프 변수의 값을 함수에 전달할 수 있습니다.

def count():
    funcs = []
    for i in [1, 2, 3]:
        def g(param):
            f = lambda: param    # 这里创建了一个匿名函数
            return f
        funcs.append(g(i))        # 将循环变量的值传给 g
    return funcs
>> > f1, f2, f3 = count()
>> > f1()
1
>> > f2()
2
>> > f3()
3

요약

  • 클로저는 자유 변수를 전달하는 함수입니다. 클로저를 생성한 외부 함수의 수명 주기가 종료되더라도 클로저가 참조하는 자유 변수는 여전히 존재합니다.

  • 클로저에는 여러 인스턴스가 실행될 수 있습니다.

  • 클로저의 루프 변수나 나중에 변경될 변수를 참조하지 마세요.

위는 Python Advanced: closure carry state의 내용입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.