簡體   English   中英

定義函數時,應按什么順序放置參數?

[英]When I define functions, in what order should I put the parameters?

我經常發現很難做出決定並且前后矛盾。 我可以遵循一些規則嗎?

例如:

def remove_except(haystack, needle, exclude_value):
    for key in hackstack:
        if key in needle and haystack[key] != exclude_value:
            hackstack.pop(key)

可能很容易是:

def remove_except(needle, exclude_value, haystack):
    for key in hackstack:
        if key in needle and haystack[key] != exclude_value:
            hackstack.pop(key)

這不是一個完美的例子,因為我傾向於將變量修改為第一個參數,例如haystack,這甚至可能是一個約定,但除此之外,我不確定該怎么做。

我對除Python外的更多語言感興趣。

唯一的規則是一致的 這不僅意味着在您定義的API之間和內部保持一致,而且還與環境中常用的任何API保持一致。 請注意,這可能意味着您在一種環境中所做的事情與在另一種環境中所做的不同。 嘗試適應。

現在,使用Python和JavaScript,您可以使用面向對象的方法至少將干草堆排除在外,因為干草堆將(或者至少可以是)您正在作用的對象,因此您將如何做由語言決定(例如, delete haystack[needle]; [用於從對象刪除屬性的JavaScript]或del haystack[needle] [用於刪除字典條目的Python])。 C不是面向對象的(C ++,D,Objective-C和其他幾種派生類),因此您需要在此處查找約定。

從主觀上來講 ,以我的經驗來看haystack通常排在第一位,但這可能只是我的經驗。 同樣,我的主觀意見是exclude_value將是最后一件事(所以haystackneedleexclude_value ),因為還有其他操作需要haystackneedlesomething_else ,但這只是一種意見。

我相信慣例從左到右,從最重要到最不重要。 因此對於您的示例,我將這樣做(針,干草堆,excluded_value)。 在這種情況下,needle最重要,因為它是呼叫的定義信息。 同一干草堆可以用另一根針在另一個通話中使用。 Exclude_value似乎是可選的。

這完全取決於您。 如果您要編寫的單個函數不同於包含項目中的任何其他函數,例如項目,則必需/重要參數排在第一位,然后是可選/不重要。 您使用的語言可能會影響選擇。 Python允許提供可選的命名參數或關鍵字參數,但它們必須遵循位置參數。

如果您正在為API編寫一組類似的函數,那么一致性就變得更加重要。 使用干草堆示例,您可能有

def insert(haystack, needle)
def remove(haystack, needle)
def remove_except(haystack, needle, exclude_value)
def copy(haystack, haystack2)

干草堆最先出現的位置,因為它是所有列出的方法的關鍵參數,

def remove(needle, haystack)
def remove_except(haystack, needle, exclude_value)

看起來很奇怪(但當然仍然可以使用)。

如果您使用一種面向對象的語言,並且發現自己編寫了一系列共享參數的函數,則可能會考慮使該對象以及對該對象進行操作的函數方法,但這可能不在問題范圍之內。

對於您選擇的語言,找到一些常用的代碼並進行研究。 如果您使用的是Python,請查看標准庫。 對於Javascript,jQuery可能不錯。

就像有關“將干草堆放在第一位”的合唱中的一些支持信息一樣, 在這種情況下,大多數情況下是針對JavaScript的 :當您考慮哪個參數是“最重要的”或哪個參數是“干草堆”時,(可以)幫助您考慮調用之間哪個參數可能不同,哪個參數可能更改。 在您的示例中,“針”在調用之間可能非常不穩定,而“干草堆”可能總是或幾乎總是相同的。

好吧,如果是這種情況–通常只對一個特定對象使用類似工具–在新的JavaScript環境中(在Function原型上)可用的“ bind()”方法,或者由Prototype或Functional這樣的庫添加,可能真的有用:

function whatever(haystack, needle) {
  // ...
};

var myHaystack = new Haystack( /* ... */ );

var myHaystackWhatever = whatever.bind(null, myHaystack);

現在可以像這樣使用函數“ myHaystackWhatever”:

var result = myHaystackWhatever(someNeedle);

這看似微不足道,但是在像JavaScript這樣的功能語言中,能夠輕松可靠地創建新功能,因為它是對現有功能的變體,因此非常方便,從而節省了許多鍵入操作和括號/括號匹配的麻煩。

這里的重點是,像“綁定”這樣的工具,尤其是在JavaScript中,它具有將調用值與形式參數完全基於順序的綁定,因此您需要從左到右綁定固定值。 因此,如果最左邊的參數是最有可能是不勝枚舉的東西,那么“ bind()”就不太有趣了。 (Functional JavaScript庫提供了一種綁定其他參數的方法,不僅從左到右,而且還很奇特,怪異,在我看來,作為一個編碼示例,它很有意思。)

我相信這完全取決於您。

在您的示例中,我將從操作對象或執行操作開始。 然后是最必要的參數。 干草堆,針,排除價值。 如果可以刪除另一個參數(例如,沒有排除的值)而使用該函數的另一個版本,則通常在最后。 我現在正在考慮使用C,但是您的示例是python,因此可以處理可選或默認參數...

除了一致性的“非正式”規則或“最重要到最不重要”之外,在Python中還需要注意一些語言規則:

函數定義可以包含(按此順序):

  • 位置參數(即沒有默認值的必需參數),
  • 關鍵字參數(即在函數定義期間指定默認值的可選參數),
  • 變量參數(即,未指定數量的未命名參數),和/或
  • 可變關鍵字參數(即,未指定數量的自由“可命名”關鍵字參數)

所以你可以寫

def myfunc(x, y, z=0, truncate=True, *args, **kwargs):
    do_something()

然后可以稱為

myfunc(1,2)
myfunc(1,2,3,False)
myfunc(1,2,3,True, "some more args", mykeyword="keyword arg")

但是您不能定義這樣的函數:

def wontwork(x=0, y, z):
def wontworkeither(*args, debug=True)

Python教程中對此進行了詳細介紹

暫無
暫無

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

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