복붙노트

[PYTHON] 외부 변수에 액세스하는 람다 함수 [duplicate]

PYTHON

외부 변수에 액세스하는 람다 함수 [duplicate]

익명의 함수로 놀고 싶었 기 때문에 간단한 프라임 파인더를 만들기로 결정했습니다. 여기있어:

tests = []
end = int(1e2)
i = 3
while i <= end:
    a = map(lambda f:f(i),tests)
    if True not in a:
        tests.append(lambda x:x%i==0)
        print i
    print tests
    print "Test: "+str(i)
    print str(a)
    i+=2

그러나 내가 찾은 것은 람다 x의 i : x % i == 0이 매번 액세스되는 반면, 나는 그것이 문자 그대로의 숫자가되기를 원한다. 어떻게하면 λ x : x % 3 == 0이 될 수 있습니까?

해결법

  1. ==============================

    1.당신은 람다를 만들 때 나는 "포획"할 수 있습니다.

    당신은 람다를 만들 때 나는 "포획"할 수 있습니다.

    lambda x, i=i: x%i==0
    

    이것은 람다의 컨텍스트에서 내가 생성되었을 때의 것과 동일하게 설정합니다. 당신은 또한 lambda x, n = i : x % n == 0이라고 말할 수 있습니다. 원한다면, 정확히 포착되지는 않지만, 필요한 것을 얻을 수 있습니다.

    당신이 본 것처럼 이것이 없다면, 그것은 둘러싼 범위에서 나는 찾을 것입니다.

    정의 된 함수를 사용하는 다음과 유사한 조회 문제입니다.

    i = "original"
    
    def print_i1():
        print(i) # prints "changed" when called below
    
    def print_i2(s=i): #default set at function creation, not call
        print(s) # prints "original" when called below
    
    
    i = "changed"
    print_i1()
    print_i2()
    
  2. ==============================

    2.문제는 테스트에서 각 함수가 변수 i를 참조한다는 것입니다.

    문제는 테스트에서 각 함수가 변수 i를 참조한다는 것입니다.

    더 일반적으로 함수 내부에서이를 수행합니다.이 경우에는 클로저에 저장되는 정의 할 수있는 범위 변수 i가 있습니다. 이러한 Nasty Closure에서 자세히 설명합니다.

    하지만 여기에서는 더 간단합니다. 저는 전역 변수이므로 닫힘이 없습니다. 함수는 실행할 때 i를 전역 변수로 찾기 위해 컴파일됩니다. i가 변경 되었기 때문에 함수가 실행될 때 변경된 값을 볼 수 있습니다. 그처럼 간단합니다.

    이것 (클로저와 전역 변수 모두에서 작동)을 둘러싼 전통적인 방법은 실제로 해킹이 아니더라도 "기본 값 해킹"으로 잘 알려져 있습니다. (FAQ의 설명을 참조하십시오.) Ryan Haining의 대답은이 작업을 수행하는 방법을 설명합니다.

    lambda x, i=i: x%i==0
    

    이렇게하면 i라는 매개 변수가 만들어지며,이 매개 변수의 기본값은 함수를 만들 때의 값과 같습니다. 그런 다음 함수 내부에서 매개 변수 i에 액세스하면 해당 값을 얻습니다.

    JavaScript와 같은 언어를 사용하는 경우 더 익숙해 보일 수있는 다른 방법은 함수 작성 함수를 작성하고 user2864740의 대답과 같이 i의 값을 해당 함수 작성 함수의 인수로 전달하는 것입니다 :

    (lambda i: lambda x: x%i)(i)
    

    이것은 여분의 매개 변수 (누군가가 실수로 인수를 전달할 수 있음)를 사용하여 함수의 서명을 "오염"시키는 것을 피하지만 정당한 이유없이 함수를 작성하고 호출하는 대가를 치러야합니다.

    세 번째 방법은 partial을 사용하는 것입니다. 래퍼 함수를 ​​정의하는 대신에 partial을 사용하여 람다 (lambda)가 더 깔끔해질 수 있으므로 함수를 부분적으로 적용하는 것이 전부입니다.

    불행히도이 경우 함수는 연산자 안에 숨겨져 있으며이를 노출하는 operator.mod 함수는 키워드 인수를 사용하지 않으므로 두 번째 피연산자를 유용하게 사용할 수 없습니다. 그래서,이 경우에는 나쁜 해결책입니다. 정말로 원한다면, 더 좋고 부분적으로 작동하는 래퍼를 작성할 수 있습니다.

    def opmod(a, b):
        return a % b
    
    partial(operator.mod, b=i)
    

    이 경우 다른 솔루션을 사용하는 것이 나을 것이라고 생각합니다. 적절한 경우에 대비하여 머리에 보관하십시오.

  3. ==============================

    3.람다를 반환하는 새 함수를 만듭니다. 그런 다음 그것을 인수로 전달하십시오. 이렇게하면 새 바인딩 범위가 만들어집니다.

    람다를 반환하는 새 함수를 만듭니다. 그런 다음 그것을 인수로 전달하십시오. 이렇게하면 새 바인딩 범위가 만들어집니다.

    def make_test (i):
       # this i refers to the parameter (which evaluates to the /value/ passed)
       return lambda x: x%i==0
    
    # ..
    # the /value/ resulting from evaluating the variable is passed
    tests.append(make_test(i))
    
  4. from https://stackoverflow.com/questions/21053988/lambda-function-acessing-outside-variable by cc-by-sa and MIT license