[英]Python - Passing Functions with Arguments as Arguments in other Functions
[英]Input arguments in Python functions
我是Python語言的新手,但我有點沮喪。
直到今天,我認為在函數調用中傳遞參數名稱不是強制性的。 例如,如果您具有以下功能:
def computeRectangleArea(width=7, height=8):
return width * height
我以為您可以像這樣的computeRectangleArea(width=7,height=8)
那樣調用computeRectangleArea(width=7,height=8)
只是為了使參數的含義更清楚,但是實際上不需要輸入參數的關鍵字,因此您也可以通過這種方式調用相同的函數: computeRectangleArea(7, 8)
今天,當使用openpyxl.styles.PatternFill()
,我意識到,調用此函數時必須使用fill_type
關鍵字。
假設您以這種方式調用函數: openpyxl.styles.PatternFill('FFFFFF','FFFFFF','solid')
,那么輸入參數的解釋將是錯誤的。
我對OOP語言(Java,C#)有一些經驗,這些東西在那兒不存在。
在我看來,某些參數名稱(例如上例中的start_color
和end_color
)是可選的,而其他參數(例如fill_type
)必須在其值之前指定,這似乎是一個不一致的行為。
有人可以解釋一下為什么這看似奇怪的政策嗎? 另外,如果有人可以向我指出一些有用的資源以了解其實現方式,我將感到非常高興。
有人可以解釋一下為什么我們需要這種“頭痛”嗎?
對於您的特定示例,似乎沒有任何僅關鍵字參數。 相反,您嘗試傳遞第一個,第二個和第四個參數的參數,而不必在您不關心的中間傳遞參數。
換句話說,這根本不是頭痛。 您可以很容易地忽略它的便利(以及健全性檢查),但可能不想這么做。
代替這個:
PatternFill('FFFFFF', 'FFFFFF', fill_type='solid')
……你可以這樣寫:
PatternFill('FFFFFF', 'FFFFFF', Color(), 'solid')
…但是為了知道那是您需要發送的內容,您需要閱讀源代碼或文檔以查看整個參數列表,並查看要跳過的參數的默認值是什么,然后顯式添加它們給你打電話。
我懷疑有人會發現更好。
而且,正如多人在注釋中指出的那樣,這幾乎完全是命名參數在C#中的工作方式。
偶然地,此類是一個很好的示例,說明了為什么Python實際上確實允許僅關鍵字的參數,即使此處未使用它們也是如此。
您可以編寫PatternFill('FFFFFF', 'FFFFFF', 'solid')
並不會因PatternFill
錯誤參數而收到TypeError
的PatternFill
,而是關於'solid'
不能用作顏色的神秘錯誤,這並不是一個好PatternFill
事情。 而且(至少沒有類型提示注釋,而這種類型沒有),IDE或任何其他工具都無法捕捉到該錯誤。
而且,實際上,通過不使用關鍵字,您甚至在沒有意識到的情況下就將初始參數弄錯了。 您幾乎肯定要這樣做:
PatternFile(None, 'FFFFFF', 'FFFFFF')
…但是您擺脫了這個錯誤,沒有明顯的錯誤:
PatternFile('FFFFFF', 'FFFFFF')
…意味着您要傳遞前景色作為圖案類型,而將背景色作為前景色傳遞,並保留默認的背景色。
這可以通過使所有或大多數參數僅使用關鍵字來解決。 但是如果沒有僅關鍵字的參數,則唯一的選擇將是**kwargs
,這種權衡通常不值得。
引用PEP 3102的原理,該提案向該語言添加了僅關鍵字參數:
在許多情況下,函數需要采用可變數量的參數。 Python語言使用'varargs'語法(* name)支持此功能,該語法指定將任何“剩余”參數作為元組傳遞給varargs參數。
對此的限制之一是,當前必須在vararg插槽之前填充所有常規參數插槽。
這並不總是可取的。 可以很容易地預想一個函數,該函數接受可變數量的參數,但也可以采用關鍵字參數形式的一個或多個“選項”。 當前,唯一的方法是定義varargs參數和'keywords'參數(
**kwargs
),然后從字典中手動提取所需的關鍵字。
如果不清楚,為什么使用*args
和**kwargs
還不夠好:
help
或自動生成的文檔中查看函數定義時,看不到函數的實際簽名。 inspect
模塊或類似模塊的動態反射代碼也無法使用該簽名。 args
和kwargs
訪問分散在整個函數主體中。 有關此功能允許使用的示例,請考慮內置print
功能,您可以這樣調用它:
print(x, y, z, sep=', ')
這行得通,因為print
的定義如下:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False):
如果不是關鍵字參數,則沒有辦法將sep
傳遞為與實際打印值不同的值。
您可以強迫用戶將所有對象傳遞給一個元組,而不是作為單獨的參數傳遞,但是那樣會不那么友好—即使您這樣做,也沒有辦法傳遞flush
而不傳遞所有值的sep
, end
和file
。
而且,即使具有關鍵字參數,如果不是僅關鍵字參數,函數簽名也必須如下所示:
print(*objects, **kwargs):
……這將使您很難確定可以傳遞哪些關鍵字參數。
位置和關鍵字參數的工作方式與您更了解的語言一樣。 您需要轉到所用方法的文檔並查看簽名。 要創建PatternFill
對象,請轉到類的__init__
方法。
class PatternFill(Fill):
def __init__(self, patternType=None, fgColor=Color(), bgColor=Color(),
fill_type=None, start_color=None, end_color=None):
您可以指定不帶關鍵字的參數,只要您按順序提供所有參數,而不會跳過任何參數。 例如,您的失敗呼叫可以合法地給出為:
PatternFill(None, 'FFFFFF', 'FFFFFF', 'solid')
這些將與前四個參數匹配。 任何時候您無序提供參數時,都必須為該參數以及該調用中的所有后續參數提供關鍵字。 例如,在上述調用中,如果要讓它們的樣式默認設置為None
,則必須為所提供的三個參數提供關鍵字。 如果您只是省略None
,那么解析器仍會嘗試從前面按順序對其進行匹配:
patternType <= 'FFFFFF'
fgColor <= 'FFFFFF'
bgColor <= 'solid'
...而您的呼叫無法通過解析。
這樣可以使事情變得有些清除嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.