문제

다음 테스트는 실패합니다.

#!/usr/bin/env python
def f(*args):
    """
    >>> t = 1, -1
    >>> f(*map(lambda i: lambda: i, t))
    [1, -1]
    >>> f(*(lambda: i for i in t)) # -> [-1, -1]
    [1, -1]
    >>> f(*[lambda: i for i in t]) # -> [-1, -1]
    [1, -1]
    """
    alist = [a() for a in args]
    print(alist)

if __name__ == '__main__':
    import doctest; doctest.testmod()

다시 말해서:

>>> t = 1, -1
>>> args = []
>>> for i in t:
...   args.append(lambda: i)
...
>>> map(lambda a: a(), args)
[-1, -1]
>>> args = []
>>> for i in t:
...   args.append((lambda i: lambda: i)(i))
...
>>> map(lambda a: a(), args)
[1, -1]
>>> args = []
>>> for i in t:
...   args.append(lambda i=i: i)
...
>>> map(lambda a: a(), args)
[1, -1]
도움이 되었습니까?

해결책

가치가 다르기 때문에 서로 다릅니다. i 생성기 표현식과 목록 comp 모두 느리게 평가됩니다. 즉,익명 함수가 호출될 때 f.
그 무렵, i 다음과 같은 경우 마지막 값에 바인딩됩니다. t, 이는 -1입니다.

따라서 기본적으로 이것은 목록 이해가 수행하는 작업입니다(genexp의 경우와 마찬가지로).

x = []
i = 1 # 1. from t
x.append(lambda: i)
i = -1 # 2. from t
x.append(lambda: i)

이제 람다는 참조하는 클로저를 가지고 다닙니다. i, 하지만 i 두 경우 모두 -1에 바인딩됩니다. 왜냐하면 그것이 할당된 마지막 값이기 때문입니다.

람다가 현재 값을 수신하는지 확인하려면 i, 하다

f(*[lambda u=i: u for i in t])

이런 식으로 평가를 강제로 수행합니다. i 클로저가 생성될 때.

편집하다:생성기 표현식과 목록 이해에는 한 가지 차이점이 있습니다.후자는 루프 변수를 주변 범위로 유출합니다.

다른 팁

Lambda는 값이 아닌 변수를 캡처하므로 코드가

lambda : i

항상 가치를 반환합니다 현재 폐쇄에 묶여 있습니다. 호출 될 때 까지이 값은 -1로 설정되었습니다.

원하는 것을 얻으려면 Lambda가 만들 때 실제 바인딩을 캡처해야합니다.

>>> f(*(lambda i=i: i for i in t)) # -> [-1, -1]
[1, -1]
>>> f(*[lambda i=i: i for i in t]) # -> [-1, -1]
[1, -1]

표현 f = lambda: i 다음과 같습니다.

def f():
    return i

표현 g = lambda i=i: i 다음과 같습니다.

def g(i=i):
    return i

i a 무료 변수 첫 번째 경우에 두 번째 경우에 함수 매개 변수에 바인딩되며,이 경우 로컬 변수입니다. 기본 매개 변수의 값은 함수 정의 시점에서 평가됩니다.

발전기 표현식은 가장 가까운 동봉 범위입니다 (여기서 i 정의) i 이름의 이름 lambda 그러므로 표현 i 해당 블록에서 해결됩니다.

f(*(lambda: i for i in (1, -1)) # -> [-1, -1]

i 로컬 변수입니다 lambda i: ... 따라서 블록이므로 참조하는 객체는 해당 블록에 정의됩니다.

f(*map(lambda i: lambda: i, (1,-1))) # -> [1, -1]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top