簡體   English   中英

functools.partial 和 functools.reduce 之間的交互

[英]Interaction between functools.partial and functools.reduce

我有一個函數,我正在嘗試創建它的部分版本,然后在 reduce 語句中應用該部分函數。

偏函數本身是有效的——因為我可以用一組參數正常調用它,它會返回正確的答案。 但是,如果在減少下應用它會中斷

例如;

import functools

test=[1,2,3,4]

def base_function(mult=10,a=0,b=0):
    return(mult*(a+b))

#control function, should act like partial base_function with mult=1
def test_function1(a=0,b=0):
    return(a+b)

#stupid partial function that has destroyed my friday afternoon
test_function2=functools.partial(base_function,mult=1)
print(test_function2.args) #returns ()
print(test_function2.keywords) #returns {'mult':1} 

print(test_function1(a=1,b=2)) #returns 3 as expected
print(test_function2(a=1,b=2)) #returns 3 as expected! horray!

#so the partial function itself works when called normally

print(functools.reduce(test_function1,test,-20)) #returns -10
print(functools.reduce(test_function2,test,-20)) #returns TypeError: base_function() got multiple values for argument 'mult'

如果我更改代碼以生成 mult 一個位置參數並更新部分函數,​​作為額外的獎勵;

def base_function(mult,a=0,b=0):
    return(mult*(a+b))


def test_function1(a=0,b=0):
    return(a+b)

test_function2=functools.partial(base_function,1)
print(test_function2.args)
print(test_function2.keywords)

該血腥的事情與reduce 語句完美配合。

任何人都可以向我解釋這一點嗎? 對於這種類型錯誤,我能找到的唯一答案似乎適用於有人將函數中的某個東西作為關鍵字和普通參數調用的情況——據我所知,這里沒有發生過——如果是這種情況正常調用時,部分函數不應正常工作。 使 mult 成為位置參數的“解決方案”是可行的,但我真的更想知道是什么導致了這個錯誤,因為顯然我一定誤解了一些關鍵的東西。

編輯:感謝回答我問題的海報 - 我現在明白為什么會發生這種情況以及為什么重新排列參數或使它們具有位置性可以解決問題,所以我將其標記為已解決。

然而,我確實想知道是否有一種“整潔”的方法來做到這一點 - 一個像部分一樣的運算符,它不只是返回一個部分對象,如果參數傳遞正確,它就像所需的函數一樣,而是從字面上返回一個任意所需的函數,沒有那個需要預定義的任意函數。 例如:

import functools

def base_function(mult=10,a=0,b=0):
    return(mult*(a+b))

def test_function1(a=0,b=0):
    return(a+b)

test_function2=partial_like_operator(base_function,mult=1)

print(test_function2==test_function1) #prints true

這一切都在參數的排序中。 在您通過使用a=1, b=2與使用前兩個參數的reduce()顯式繞過順序的測試用例中,它確實失敗了。

但是,如果你把它轉過來,這似乎有效:

def base_function(a=0, b=0, mult=10):
    return mult * (a + b)

這似乎對我有用,至少!

在您的情況下,以下很可能也會失敗:

print(test_function2(1, 2))

這是因為它試圖設置mult ...

@horoy 是對的。

另一種解釋方式:

在幕后,調用reduce會產生錯誤,最終調用如下:

test_function2(x, y, mult=1)

其中xyreduce函數的局部變量。

您可以嘗試一下,很容易親眼看到這不是一個有效的調用。 傳遞的第一個參數必須對應於mult因為這是函數的第一個參數,但隨后mult被傳遞了另一個值,作為 kw arg。

在您調用起作用的部分函數的測試中,您將ab作為 kwargs 傳遞,從而繞過了這個問題。

結論是,在使用 partial 時,最好將其設計為綁定函數的最后一個參數,而不是第一個參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM