루프의 Python Lambda
다음 코드 스 니펫을 고려하십시오.
# directorys == {'login': <object at ...>, 'home': <object at ...>}
for d in directorys:
self.command["cd " + d] = (lambda : self.root.change_directory(d))
다음과 같이 두 가지 기능의 사전을 만들 것으로 예상합니다.
# Expected :
self.command == {
"cd login": lambda: self.root.change_directory("login"),
"cd home": lambda: self.root.change_directory("home")
}
그러나 생성 된 두 개의 람다 함수가 정확히 동일한 것처럼 보입니다.
# Result :
self.command == {
"cd login": lambda: self.root.change_directory("login"),
"cd home": lambda: self.root.change_directory("login") # <- Why login ?
}
왜 그런지 정말 모르겠어요. 의견 있으십니까 ?
생성 된 각 함수에 대해 d를 바인딩해야합니다. 이를 수행하는 한 가지 방법은 기본값을 사용하여 매개 변수로 전달하는 것입니다.
lambda d=d: self.root.change_directory(d)
이제 함수 내부의 d는 이름이 같더라도 매개 변수를 사용하고 함수가 생성 될 때 그 기본값이 평가됩니다. 이것을 볼 수 있도록 :
lambda bound_d=d: self.root.change_directory(bound_d)
개체를 바인딩하기 때문에 목록 및 사전과 같은 변경 가능한 개체의 경우와 같이 기본값이 작동하는 방식을 기억하십시오.
기본값이있는이 매개 변수 관용구는 충분히 일반적이지만 함수 매개 변수를 조사하고 그 존재에 따라 수행 할 작업을 결정하면 실패 할 수 있습니다. 다른 클로저로 매개 변수를 피할 수 있습니다.
(lambda d=d: lambda: self.root.change_directory(d))()
# or
(lambda d: lambda: self.root.change_directory(d))(d)
이것은 d가 바인딩되는 지점 때문입니다. 람다 함수는 모두 현재 값 이 아닌 변수를 가리 키 므로 다음 반복에서 업데이트하면이 업데이트가 모든 함수에 표시됩니다.d
d
더 간단한 예 :
funcs = []
for x in [1,2,3]:
funcs.append(lambda: x)
for f in funcs:
print f()
# output:
3
3
3
다음과 같이 추가 기능을 추가하여이 문제를 해결할 수 있습니다.
def makeFunc(x):
return lambda: x
funcs = []
for x in [1,2,3]:
funcs.append(makeFunc(x))
for f in funcs:
print f()
# output:
1
2
3
람다 식 내부의 범위를 수정할 수도 있습니다.
lambda bound_x=x: bound_x
그러나 일반적으로 함수의 시그니처를 변경했기 때문에 이것은 좋은 습관 이 아닙니다 .
I met the same problem. The selected solution helped me a lot, but I consider necessary to add a precision to make functional the code of the question: define the lambda function outside of the loop. By the way, default value is not necessary.
foo = lambda d: lambda : self.root.change_directory(d)
for d in directorys:
self.command["cd " + d] = (foo(d))
Alternatively, instead of lambda
, you can use functools.partial
which, in my opinion, has a cleaner syntax.
Instead of:
for d in directorys:
self.command["cd " + d] = (lambda d=d: self.root.change_directory(d))
it will be:
for d in directorys:
self.command["cd " + d] = partial(self.root.change_directory, d)
Or, here is another simple example:
numbers = [1, 2, 3]
lambdas = [lambda: print(number)
for number in numbers]
lambdas_with_binding = [lambda number=number: print(number)
for number in numbers]
partials = [partial(print, number)
for number in numbers]
for function in lambdas:
function()
# 3 3 3
for function in lambdas_with_binding:
function()
# 1 2 3
for function in partials:
function()
# 1 2 3
ReferenceURL : https://stackoverflow.com/questions/19837486/python-lambda-in-a-loop
'IT story' 카테고리의 다른 글
Dapper로 DateTime을 UTC로 가져 오기 (0) | 2021.01.07 |
---|---|
CSV 파일을 사용하여 플로팅 (0) | 2021.01.07 |
DOM 리플 로우 란 무엇입니까? (0) | 2021.01.07 |
Dataframe의 모든 열에서 NaN이 아닌 항목 수 계산 (0) | 2021.01.07 |
.NET 솔루션에서 사용하지 않는 리소스 찾기 (0) | 2021.01.07 |