2 回答

TA貢獻1827條經驗 獲得超8個贊
正如Elegant Odoo 的回答所指出的,Python lambdas 通過引用捕獲變量。
搜索答案時您可能會聽到的另一個術語是“后期綁定”,這意味著只有在執行 lambda 時才會將 lambda 內的變量綁定到它的實際值。結果,您創建的所有 lambda 函數都具有相同的(和最終的)值k,這會導致無限遞歸。
雖然exec基于 - 的方法是有效的,但我認為大多數人都會同意exec在實際代碼中應該避免這種做法。對此的替代解決方案是通過函數創建 lambda 函數以強制早期綁定:
n = 3
func_list = [lambda x: 1]
def create_fn(k_val):
return lambda x: func_list[k_val - 1](x) * (x + k_val)
for k in range(1, n):
func_list.append(create_fn(k))
print(list(map(lambda f: f(1), func_list)))
當您調用create_fnwith 時k, 的當前值將k傳遞給 name 下的函數k_val。然后k_val將 lambda 函數中的k_val變量綁定到 范圍內的變量,并在調用它時create_fn使用 的值。k

TA貢獻1844條經驗 獲得超8個贊
一個很好的案例來解釋 Reference 和 Value 之間的區別:
讓我解釋一下為什么會發生這種情況,以了解發生了什么讓我們使用普通函數,以便我們可以調試 K 的值:
n = 3
func_list = [lambda x : 1]
for k in range(1,n):
def f(x):
print('K is: ', k)
return func_list[k-1](x) * (x + k)
func_list.append(f)
# just print will be enough to cause error
print(func_list[2])
輸出是:
K is : 2
K is : 2
K is : 2
K is : 2
K is : 2
....
....
....
....
RecursionError: maximum recursion depth exceeded while calling a Python object
您在所有方法中使用相同的變量(對 value 的引用)。K 引用循環生成的值 2。
在循環 make 結束后進行演示k = 5,這將引發錯誤index out of range。
一個簡單的解決方案exec:
n = 3
func_list = [lambda x: 1]
for k in range(1, n):
# here you are not using variable k we are using the value it's like
# we are rewriting it to code every time but is not you who typing it's the compute -_^
exec('func_list.append(lambda x : func_list[{k}-1](x) * (x + {k}))'.format(k=k))
# lambda print(f(1)) will create [None, None, None] I removed the print
print(list(map(lambda f: f(1), func_list)))
輸出:
[1, 2, 6]
詛咒上述解決方案適用于您的情況,因為K它只是一個簡單Integer 的假設,K它是一個非常復雜的對象,具有復雜的屬性和私有變量。為了達到同樣的目的,您需要重建對象。
# we need to consract another object using the value
exec('... KClass({}, {}, {}) ...'.format(k.attr1, k.attr2, k.attr2))
KClass使用您的屬性 Object 的成像XClass將需要構造兩個 object k and x。
所以使用exec工廠模式是不實際的更好的方法來處理這個問題:
n = 3
func_list = [lambda x: 1]
def method_factory(k):
# here K reference it's not the same K reference that is created
# in loop there are different but with the alias K
return lambda x: func_list[k - 1](x) * (x + k)
for k in range(1, n):
func_list.append(method_factory(k))
print(list(map(lambda f: f(1), func_list)))
為什么會這樣,因為當您調用method_factory它時,它將創建自己的范圍,其中包含一個帶有別名的引用,K該引用指向value的引用指向的引用相同。Kloop
希望你明白這一切都是關于reference和的scopes。
添加回答
舉報