簡體   English   中英

派生類是否自動擁有基類的所有屬性?

[英]Does a derived class automatically have all the attributes of the base class?

似乎沒有好的在線文檔:如果我創建一個派生類,它會自動擁有基類的所有屬性嗎? 但是什么是BaseClass.__init() ,你還需要對其他基類方法做嗎? BaseClass.__init__()是否需要參數? 如果您有基類__init__() ,它們是否也被派生類使用,您是否需要顯式設置派生classe的__init__() ,或者將它們設置為BaseClass.__init__()

如果在從BaseClass派生的類中實現__init__ ,那么它將覆蓋繼承的__init__方法,因此永遠不會調用BaseClass.__init__ 如果你需要為BaseClass調用__init__方法(通常就是這種情況),那么由你來做,並通過調用BaseClass.__init__顯式完成,通常來自新實現的__init__方法。

class Foo(object):
    def __init__(self):
        self.a = 10

    def do_something(self):
        print self.a

class Bar(Foo):
    def __init__(self):
        self.b = 20

bar = Bar()
bar.do_something()

這將導致以下錯誤:

AttributeError: 'Bar' object has no attribute 'a'

因此, do_something方法已按預期繼承,但該方法需要設置屬性a ,它永遠不會因為__init__也被覆蓋。 我們通過在Bar.__init__明確調用Foo.__init__來解決Bar.__init__

class Foo(object):
    def __init__(self):
        self.a = 10

    def do_something(self):
        print self.a

class Bar(Foo):
    def __init__(self):
        Foo.__init__(self)
        self.b = 20

bar = Bar()
bar.do_something()

按預期打印10張。 在這種情況下, Foo.__init__需要一個參數,它是Foo一個實例(按照慣例,它被稱為self )。

通常,當您在類的實例上調用方法時,類實例將作為第一個參數自動傳遞。 類實例上的方法稱為綁定方法 bar.do_something是綁定方法的一個示例(您將注意到它在沒有任何參數的情況下被調用)。 Foo.__init__是一個未綁定的方法,因為它沒有附加到Foo的特定實例,因此需要顯式傳遞第一個參數,即Foo的實例。

在我們的例子中,我們將self傳遞給Foo.__init__ ,這是傳遞給Bar中的__init__方法的Bar的實例。 由於Bar繼承自FooBar的實例也是Foo實例,因此允許將self傳遞給Foo.__init__

很可能是您繼承的類需要或接受的參數多於該類的實例。 這些處理方式與您在__init__調用的任何方法一樣處理:

class Foo(object):
    def __init__(self, a=10):
        self.a = a

    def do_something(self):
        print self.a

class Bar(Foo):
    def __init__(self):
        Foo.__init__(self, 20)

bar = Bar()
bar.do_something()

哪個會打印20

如果您嘗試通過繼承類實現完全公開基類的所有初始化參數的接口,則需要明確地這樣做。 這通常使用* args和** kwargs參數(名稱按慣例)來完成,這些參數是未明確命名的所有其余參數的占位符。 以下示例使用了我討論過的所有內容:

class Foo(object):
    def __init__(self, a, b=10):
        self.num = a * b

    def do_something(self):
        print self.num

class Bar(Foo):
    def __init__(self, c=20, *args, **kwargs):
        Foo.__init__(self, *args, **kwargs)
        self.c = c

    def do_something(self):
        Foo.do_something(self)
        print self.c


bar = Bar(40, a=15)
bar.do_something()

在這種情況下,參數c設置為40,因為它是Bar.__init__的第一個參數。 然后將第二個參數合並到變量argskwargs (*和**是特定的語法,表示在傳遞給函數/方法時將列表/元組或字典擴展為單獨的參數),並傳遞給Foo.__init__

此示例還指出,如果需要,則需要顯式調用任何重寫方法(在本例中為do_something )。

最后一點,您將經常看到super(ChildClass, self).method() (其中ChildClass是一些任意子類),而不是顯式調用BaseClass方法。 關於super討論是另一個問題,但足以說明,在這些情況下,它通常被用來通過調用BaseClass.method(self)完成正在做的事情。 簡而言之, super將方法調用方法調用到方法解析順序中的下一個類--MRO(在單繼承中是父類)。 有關詳細信息,請參閱super上文檔

如果我創建一個派生類,它會自動擁有基類的所有屬性嗎?

類屬性,是的。 實例屬性,否(僅僅因為它們在創建類時不存在),除非派生類中沒有__init__ ,在這種情況下將調用基本類,並將設置實例屬性。

是BaseClass。 init ()需要參數嗎?

取決於班級及其__init__簽名。 如果您在派生類中顯式調用Base.__init__ ,則至少需要將self作為第一個參數傳遞。 如果你有

class Base(object):
    def __init__(self):
        # something

那么很明顯__init__沒有接受其他論點。 如果你有

class Base(object):
    def __init__(self, argument):
        # something

那么你在調用base __init__時必須傳遞argument 這里沒有火箭科學。

如果您的基類init ()有參數,它們是否也被派生類使用,您是否需要顯式設置派生classe的init ()的參數,或者將它們設置為BaseClass。 init ()而不是?

同樣,如果派生類沒有__init__ ,則將使用基礎類。

class Base(object):
    def __init__(self, foo):
        print 'Base'

class Derived(Base):
    pass

Derived()   # TypeError
Derived(42) # prints Base

在其他情況下,你需要以某種方式照顧它。 你是否使用*args, **kwargs並且只是將未修改的參數傳遞給基類,或者復制基類簽名,或者從其他地方提供參數,取決於你想要完成的任務。

暫無
暫無

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

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