2017-02-26 51 views
0

我試圖使用增強而不是重寫基類的子類。我正在使用super方法來調用基類。我發現我需要使用__init__中的名稱修改功能(但僅在init中)才能使代碼正常工作。因此,我做了這個打印的例子。因爲我沒有使用名字改編我期望它來調用子類兩次,當我做初始化,而是調用基類在__init__中的python名稱mangling似乎不一致

似乎__init__有時出現的基類,有時看到子類。我相信這只是我的一個不完全的理解,但是當我在打印示例中調用基類和子類時,是否需要爲真實代碼命名?

代碼

class base: 
    def __init__(self): 
     self.print() 

    def print(self): 
     print("base") 

class subclass(base): 
    def __init__(self): 
     super(subclass, self).__init__() 
     self.print() 

    def print(self): 
     super(subclass, self).print() 
     print("subclass") 

x = base() 
x.print() 
print("--") 
y = subclass() 
y.print() 

輸出 - 爲什麼不y = subclass()打印subclass而不是base,因爲我沒有使用名字改編?

> ./y.py 
base 
base 
-- 
base 
subclass 
base 
subclass 
base 
subclass 

斷碼的時候我不使用名稱改編,作品,當我用self.__set__set = set(註釋代碼)。它得到以下錯誤,當我不使用__set

File "./x.py", line 5, in __init__ 
    self.set(arg) 
TypeError: set() missing 1 required positional argument: 'arg2' 

代碼:

class base: 
    def __init__(self, arg): 
     self.set(arg) 
     # self.__set(arg) 

    # __set = set 

    def set(self, arg): 
     self.arg = arg 

    def print(self): 
     print("base",self.arg) 

class subclass(base): 
    def __init__(self, arg1, arg2): 
     super(subclass, self).__init__(arg1) 
     self.set(arg1, arg2) 

    def set(self, arg1, arg2): 
     super(subclass, self).set(arg1) 
     self.arg2 = arg2 

    def print(self): 
     super(subclass, self).print() 
     print("subclass", self.arg2, self.arg) 

x = base(1) 

x.print() 
x.set(11) 
x.print() 

y = subclass(2,3) 

y.print() 
y.set(4,5) 
y.print() 

======= =======更新

我重寫了代碼看起來像這樣:

class base: 
    def __init__(self): 
     print("base init") 
     self.print() 

    def print(self): 
     print("base print") 

class subclass(base): 
    def __init__(self): 
     print("sc init") 
     super(subclass, self).__init__() 
     print("sc after super") 
     self.print() 

    def print(self): 
     print("subclass print start") 
     super(subclass, self).print() 
     print("subclass print") 

y = subclass() 
print("--") 
y.print() 

,當我跑我得到這個輸出:

sc init 
base init 
subclass print start <<<< why is the subclass print called here 
base print 
subclass print 
sc after super 
subclass print start 
base print 
subclass print 
-- 
subclass print start 
base print 
subclass print 

爲什麼當我啓動子類時,底層init中的self.print調用子類打印?我期待那個打印基地。當我在init之外調用它時,它會調用基本打印。

回答

2

子類print明確調用父之一。所以每次調用subclass.print時,都會打印出「base」和「subclass」。這發生三次,因爲您撥打print方法三次:subclass.__init__,base.__init__(調用subclass.__init__)和subclass.print(它調用超類的版本)。

在您的「設置」示例中,subclass.__init__調用base.__init__,它嘗試僅使用一個參數調用self.set。但是由於您正在實例化subclass,self.setsubclass.set,它有兩個參數。

目前還不清楚你試圖用這些例子來達到什麼目的。您的子類並不需要致電base.__init__,因爲所有可以做的事情是致電base.set,並且您已從subclass.set調用該子類。所以,即使您的所有通話都成功了,也會導致某些方法被多次呼叫,就像print示例一樣。

我的印象是,你有點被帶走並試圖讓每個方法調用它的超類版本。這並不總是一個好主意。如果你編寫了一個子類,並且它調用了一個超類方法,那麼你需要確保子類仍然提供一個與超類所期望的接口兼容的接口。如果沒有,你可能需要而不是調用超類方法,而是讓子類將其「內聯」功能結合起來(儘管如果世界上的其他類已經對基類如何做出假設,這可能會更危險作品)。結果是你總是需要考慮哪些方法稱爲哪些人;你不能隨便調用每一個超類方法,並期待它的工作。

+0

我打電話給兩個打印看看會發生什麼。我正在研究調用超類版本來理解流程。我認爲你打我的問題,雖然。基類有一個arg,而子類有兩個。當我試圖通過超級調用基類時,該方法有2個參數,並且沒有匹配。我將不得不考慮那一刻。仍然有點困惑,爲什麼名字mangling使它的工作。 – kdubs

+0

@kdubs:這個名字讓它變得可行,因爲在名稱改變的情況下,這個方法的每個版本本質上是分開的,並且不能被子類覆蓋。所以每個類都會一直在調用它自己的實現。但這通常不是你想要的,因爲子類不能覆蓋基類實現。基本的問題是你不能採用一個需要一個參數的方法,並用一個需要兩個參數的方法來覆蓋它;任何用一個調用它的代碼現在都會失敗。 (在很多情況下,這可以通過爲第二個參數給出默認值來處理。) – BrenBarn

+0

請參閱我的更新。打印在init函數中的調用不會按照我期望的方式工作 – kdubs

相關問題