2017-07-13 81 views
1

什麼是對這個普遍的共識:Python:函數與多個函數的鍵?

def stock_amend(self, key, quantity): 
    if key == "add": 
     self.stock_quantity += quantity 
    elif key == "remove": 
     self.stock_quantity -= quantity 
    ... 

VS

def stock_add(self, quantity): 
    self.stock_quantity += quantity 

def stock_remove(self, quantity): 
    self.stock_quantity -= quantity 

... 

這兩個是一個更好的方式來定義簡單,類似的功能?使用關鍵字還是隻定義多個功能?

+3

我可能會去爲兩個單獨的功能的可讀性。我認爲使用stock_remove(4)或stock_add(4)更容易,然後做stock_amend(「remove」,4)和stock_amend(「add」,4)。但對我來說,主要是爲了可讀性。 – gavsta707

+1

可讀性通常是成功項目中最重要的事情之一,所以是的,選擇第二種選擇。閱讀和推理更容易。 –

回答

4

我最習慣看到它的方式是使用類:

class Stock: 
    def add(self, quantity): 
     self.stock_quantity += quantity 
    def remove(self, quantity): 
     self.stock_quantity -= quantity 

或者,如果邏輯是相同的,你可以只做出改變方法:

def stock_change(self, delta): 
    self.stock_quantity += delta 

並將負值傳遞給它以產生負面變化。

一個人認爲你要非常小心,雖然確保你有一個乾淨的api。作爲程序不同部分之間的邊界,通常是程序中最難改變的部分。一般來說,你想要一個功能只做一件事。這被稱爲單一責任原則。在你繼續之前,谷歌「如何設計一個API」並閱讀人們對它的想法。許多這些意見都是以來得難得的經驗而建立的。

它最終取決於你想要什麼。你比我更瞭解你的應用程序。

我不認爲自己是專家,但我確實有意見。國防部,如果這是太基於觀點/沒有幫助,請編輯/刪除它。

如果股票是您的代碼中相對不重要的一小部分,我可能會使用stock_change方法(也許將其重命名爲描述股票線性變化的內容,所以稍後如果您想說,增加一個股票10%,這也是一個「stock_change」,你會有更少的模糊函數名稱)。我建議這樣做的原因是因爲它的代碼較少,如果需要的話,您可以稍後將其重構爲第二種方法(假設您尚未將其分發給客戶)。谷歌「YAGNI」。

如果你正在用股票做很多事情,那最好是把它做成自己的類。然後,您可以對它進行子類化,將其他類似的「粗壯」功能分組給它,等等。谷歌「爲什麼是OOP」。

除非您有很好的理由,否則我會避免將該字符串用作API的一部分。作爲一個API參數的字符串很難重構 - 它們已經被用於用戶輸入和輸出(可能還有其他我現在沒有考慮的東西),許多程序員一直在努力去理解哪些字符串是哪個字符串。另外,請記住任何字符串都可以傳遞給您的api,並且您必須每次都過濾它。他們打字很弱。相反,如果你想使用一個具有大多數(全部?)字符串優點的方法,但仍然能夠限制傳遞給你函數的東西的數量,請考慮enums

總之,上述每種方法都有優點和缺點。我可能還沒有考慮更多的方法(我不認爲自己是這方面的專家),但你最瞭解你的問題域,即使你這次錯了,你會下次能夠從中學習。只要繼續閱讀,不斷重構,你就會知道一個好的API和一個糟糕的API。

+0

太棒了!所以在這種情況下,我如何分類這個/這些功能?我可以說修改庫存的功能(包括添加和刪除項目)都可以是單一責任功能。還是這還算做兩件事? – Lijok

+0

更新答案 – Ben

0

我可以推薦第三種方法使用運營商模塊?

import operator 

mapping = { 
    'add': operator.add, 
    'remove': operator.neg, 
} 

def stock_amend(self, key, quantity): 
    return mapping.get(key)(self.stock_quantity, quantity) 
+1

這並沒有回答這個問題,真的,它只是提供了'stock_amend'函數的替代實現... –

+1

那麼爲什麼替代實現不能成爲問題的答案? –

+0

它如何提出「什麼是首選方法,方法1或方法2」?你只是回答「這是方法2的替代實施」,請看我的意思? –

1

可能有多種方法,例如,發送函數stock_amend實際進行修改,等等。

除非我們需要更高的靈活性(由#1提供)在編譯時間(#2)中定義的東西是合理的,以便更輕鬆地進行靜態分析,更簡單的代碼審查等等。

0

傳遞字符串是一種糟糕的模式。要麼主叫方必須記住所有可能的密鑰,否則他們將不得不從源頭訪問其定義。您現在可能還記得這些值,但過了一段時間,我們總會忘記這些事情,而任何新編寫代碼的人也都會遇到困難。通過單獨的定義,大多數編輯提供的自動完成功能將爲您完成這項工作,並且在殼牌dir()help()中提供幫助。

除此之外,你可能不得不在未來添加這些函數的條件,只有一個函數會使它更加複雜。

def stock_add(self, quantity): 
    assert quantity > 0 
    self.stock_quantity += quantity 

def stock_remove(self, quantity): 
    assert quantity > 0 and self.stock_quantity - quantity >= 0 
    self.stock_quantity -= quantity 

如果你有多個函數做幾乎相同的事情,你可以在一個私有方法中編寫公共邏輯。

def _update_stock_quantity(self, quantity): 
    self.stock_quantity += quantity 

def stock_add(self, quantity): 
    assert quantity > 0 
    self._update_stock_quantity(quantity) 

def stock_remove(self, quantity): 
    assert quantity > 0 and self.stock_quantity - quantity >= 0 
    self._update_stock_quantity(-quantity) 

記住代碼讀取超過它被寫入

0

我建議定義多個函數,因爲它保持你的代碼清晰+簡明,這使得代碼更強大。每個功能應該有一個特定的任務,不應該依賴諸如關鍵字之類的東西。這也將允許您更容易地在其他程序中重用您的功能。下面我寫了一種方法來訪問每個函數,而不需要使用ifelif語句,這樣您的代碼就不會重複。

class Stock(): 

    def __init__(self,stock_quantity): 
     self.stock_quantity = stock_quantity 

    def stock_add(self, quantity): 
     self.stock_quantity += quantity 

    def stock_remove(self, quantity): 
     self.stock_quantity -= quantity 

    def update(self,interact,quantity=0): 
     try: 
      getattr(self,interact)(quantity) 
     except AttributeError: 
      pass 
     except TypeError: 
      print(getattr(self,interact)) 



def main(): 

    stock_obj = Stock(5) 

    stock_obj.update("stock_quantity") 
    stock_obj.update("stock_add",1) 
    stock_obj.update("stock_quantity") 

if __name__ == "__main__": 
    main()