簡體   English   中英

Python函數中的輸入參數

[英]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_colorend_color )是可選的,而其他參數(例如fill_type )必須在其值之前指定,這似乎是一個不一致的行為。

有人可以解釋一下為什么這看似奇怪的政策嗎? 另外,如果有人可以向我指出一些有用的資源以了解其實現方式,我將感到非常高興。

有人可以解釋一下為什么我們需要這種“頭痛”嗎?

對於您的特定示例,似乎沒有任何僅關鍵字參數。 相反,您嘗試傳遞第一個,第二個和第四個參數的參數,而不必在您不關心的中間傳遞參數。

換句話說,這根本不是頭痛。 您可以很容易地忽略它的便利(以及健全性檢查),但可能不想這么做。

代替這個:

PatternFill('FFFFFF', 'FFFFFF', fill_type='solid')

……你可以這樣寫:

PatternFill('FFFFFF', 'FFFFFF', Color(), 'solid')

…但是為了知道那是您需要發送的內容,您需要閱讀源代碼或文檔以查看整個參數列表,並查看要跳過的參數的默認值是什么,然后顯式添加它們給你打電話。

我懷疑有人會發現更好。

而且,正如多人在注釋中指出的那樣,這幾乎完全是命名參數在C#中的工作方式。


偶然地,此類是一個很好的示例,說明了為什么Python實際上確實允許僅關鍵字的參數,即使此處未使用它們也是如此。

您可以編寫PatternFill('FFFFFF', 'FFFFFF', 'solid')並不會因PatternFill錯誤參數而收到TypeErrorPatternFill ,而是關於'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模塊或類似模塊的動態反射代碼也無法使用該簽名。
  • 該簽名也不適用於靜態反射代碼,例如許多IDE用於完成和建議的簽名。
  • 該功能的實現還不太清楚,因為充其量只是提取和測試參數的一半樣板,最壞的情況下, argskwargs訪問分散在整個函數主體中。

有關此功能允許使用的示例,請考慮內置print功能,您可以這樣調用它:

print(x, y, z, sep=', ')

這行得通,因為print的定義如下:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False):

如果不是關鍵字參數,則沒有辦法將sep傳遞為與實際打印值不同的值。

您可以強迫用戶將所有對象傳遞給一個元組,而不是作為單獨的參數傳遞,但是那樣會不那么友好—即使您這樣做,也沒有辦法傳遞flush而不傳遞所有值的sependfile

而且,即使具有關鍵字參數,如果不是僅關鍵字參數,函數簽名也必須如下所示:

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.

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