2014-11-22 95 views
3

方法默認參數顯然可以覆蓋:如何在python中重寫方法默認參數?

>>> class B: 
...  def meth(self, r=True): print r 
>>> class D(B): 
...  def meth(self, r=False): print r 
... D().meth() 
False 
>>> B().meth() 
True 

這怎麼可能?它被認爲是不好的風格?

+0

補遺(2014年11月23日):用例是一個默認參數添加到修改遺留代碼的方法的行爲 - 並不意味着由主叫方設置 - 應命名'_r' – 2014-11-23 19:52:43

回答

5

您可以以任意方式更改重寫方法的簽名。 Python並不關心:

class Base: 
    def foo(self, x, y): 
     pass 

class Deriv(Base): 
    def foo(self, blah=100): 
     pass 

但如果你問

是不是認爲是壞的風格?

答案是肯定的,因爲它違反了重要Liskov substitution principle

如果DERIV延伸基地,你必須能夠取代DERIV基地的所有事件不會破壞你的程序。

換句話說,派生類必須滿足基類提供的所有契約。特別是,重寫的方法必須具有相同的簽名和相似的語義。由於Python不幫你,你必須手動控制,以你的IDE的幫助下(這裏的IntelliJ IDEA):

enter image description here

要獲得關於覆蓋默認參數,可以我想具體的問題答案是「視情況而定」。如果該參數是隻在內部使用,不影響物體的觀察行爲的選擇,沒有什麼錯要改變它:

class Buffer: 
    def __init__(self, init_size=16): 

class BigBuffer(Buffer): 
    def __init__(self, init_size=1024): 

在另一邊,如果帕拉姆大大影響語義,這是一個合同的一部分,不應被覆蓋。例如,該代碼將是混亂

class Test: 
    def test_equal(self, a, b, fail_if_equal=False): 

class MyTest(Test): 
    def test_equal(self, a, b, fail_if_equal=True): 
+0

Pycharm?是的,我用這個。回覆:我知道改變簽名的風格很糟糕(甚至在圖像中顯示的Pycharm中有警告),但在這種特定情況下,我更改了默認值 - 沒有任何警告。我認爲這是合法的,因爲Derived.meth()應該有不同的行爲 - 我只是通過更改默認值來實現... – 2014-11-22 14:33:03

+0

@Mr_and_Mrs_D:更新了答案以解決您的具體問題。 – georg 2014-11-22 15:15:28

+0

謝謝 - 圖片中是Intellij IDEA或Pycharm嗎? – 2014-11-22 19:41:39

0

這是絕對允許的,但可能會讓您的呼叫者感到困惑。他們是不是應該能夠使用D對象,就像它是一個B對象一樣?

+0

是的,永遠不會傳遞參數;) - 什麼是機制? – 2014-11-22 13:42:51

0

這怎麼可能?
什麼是機制?

您只需在派生類中覆蓋整個方法即可。