簡體   English   中英

在python中返回多個值而不破壞以前的代碼

[英]return multiple values in python without breaking previous code

我有一個函數的版本1,如:

def f(a,b,c):
    #Some processing
    return some_result

后來,我將其升級到版本2。

def f(a,b,c):
    #Some processing
    #Some more processing
    return some_result, additional_result

后一版本返回一個元組。 因此,使用版本1的所有客戶端代碼都已過時。 我可以按需獲得additional_result嗎?

這就是你得到additional_result當你問它,而你繼續只得到some_result仿佛什么都沒有改變。

我想到的一個技巧:

def f(a,b,c, need_additional = False):
    #Some processing
    #Some more processing
    if not need_addional:
        return some_result
    else:
        return some_result, additional_result

還有什么更好的? 還是更通用的?

我認為更優雅的解決方案是讓您的舊功能成為新功能的傳統包裝器:

def f(a,b,c):
    some_result, additional_result = f_new(a,b,c)
    return some_result

def f_new(a,b,c):
    #Some processing
    #Some more processing
    return some_result, additional_result

我不得不承認我主要使用你建議的模式,而不是我的:),但是向后兼容的默認參數並不是很好的練習。

添加additional_result作為some_result字段

如果需要,將some_result更改為繼承其數據類應該是什么的類,但使用additional_result (所以遺留代碼可以簡單地忽略你的“額外位”)

甚至更好。

只需創建返回多個值的單獨函數。 親吻;)

這些解決方案都不是完美的。

  1. 基於標志(提問者的提議)的靈活回報很難維護並且打破任何明確的API結構。
  2. Legacy wrappers(Dvir Volk的回答)將為您的API添加越來越多的功能,從而讓它成長。 它也沒有蓋上東西; 對於任何新的額外返回值,您將再次執行此操作。
  3. 只有在您可以控制結果的創建時,才能進行結果增強(Przemo Li的答案)。 如果你想返回一些庫為你創建的值,你所能做的只是在它周圍放一個包裝器(一旦由於庫更新或類似的結果類改變就會出現問題)。
  4. 對所有使用代碼進行新的API進行簡化和重構並不總是一種選擇,例如,如果您的客戶使用代碼來維護它。
  5. 附加功能(也在Przemo Li的回答和聲明的KISS中)也將使您的API混亂。

實際上,雖然看起來確實很難看,但我想我更喜歡已經提到的通過out-parameters傳遞額外結果的方法。 我的編碼方式是這樣的:

老來電者:

result = f(a, b, c)
print result

新來電者:

additionalResult = [0]
result = f(a, b, c, additionalResult)
print result, additionalResult[0]

被調用者:

def f(a, b, c, additionalResult=[None]):
    #Some processing
    #Some more processing
    additionalResult[0] = someValue
    return some_result

這也是很好的,經常在C中練習,所以有充分的理由相信這不會是我們可能忽略的陷阱,盡管它可能看起來很難看。

雖然我不是Python專家,但我會按照你提到的方式實現它,在我看來,為了實現向后兼容,我認為這是一個非常直接的改變。

如果您不必在同一文件中同時使用這兩個版本,則可以通過包含該方法的2個版本的模塊來控制它,然后僅在調用模塊中導入所需的版本。 然后,當您最終完成並重構舊代碼時,您所要做的就是在完成后更改import語句。

或者,使用from x import y as z構造,同時在同一模塊中實現這兩種實現。

您還可以在字典中返回額外值作為引用,其引用作為額外參數傳遞,例如:

def f(a,b,c, additional_result_dict = {}):
    #Some processing
    #Some more processing
    additional_result_dict['additional_result'] = additional_result
    return some_result

我終於實現它了:

def f(a,b,c, v2 = False):
    #Some processing
    #Some more processing
    if not v2:
        return some_result
    else:
        v2_dict = {}
        v2_dict['additional_result'] = additional_result
        v2_dict['...'] = ...
        return some_result, v2_dict

好處:

  • 舊版代碼不會中斷。
  • 未來版本中的返回值沒有限制。
  • 代碼是可管理的。

暫無
暫無

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

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