似乎沒有好的在線文檔: 如果我創建派生類,它是否會自動擁有基類的所有屬性?但是什麼是BaseClass.__init()
,你是否也需要對其他基類方法做? BaseClass.__init__()
需要參數嗎?如果你有基類__init__()
的參數,它們是否也被派生類使用,你是否需要明確地將參數設置爲派生類的參數__init__()
,或將它們設置爲BaseClass.__init__()
而不是?Python派生類和基類的屬性?
回答
If I make a derived class, will it automatically have all the attributes of the base class?
類屬性,是的。實例屬性,no(僅僅因爲它們在創建類時不存在),除非在派生類中沒有__init__
,在這種情況下,將調用基本類,並設置實例屬性。
Does BaseClass.init() need arguments?
取決於類和它的__init__
簽名。如果您明確地在派生類中調用Base.__init__
,則至少需要通過self
作爲第一個參數。如果你有
class Base(object):
def __init__(self):
# something
那麼很明顯,__init__
沒有其他參數被接受。如果你有
class Base(object):
def __init__(self, argument):
# something
,那麼你必須調用基__init__
時候該傳球argument
。這裏沒有火箭科學。
If you have arguments for your base class init(), are they also used by the derived class, do you need to explicitly set the arguments to the derived classe's init(), or set them to BaseClass.init() instead?
再次,如果派生類沒有__init__
,基地一個將被用來代替。
class Base(object):
def __init__(self, foo):
print 'Base'
class Derived(Base):
pass
Derived() # TypeError
Derived(42) # prints Base
在其他情況下,您需要以某種方式照顧它。無論您使用*args, **kwargs
,只是將未修改的參數傳遞給基類,或者複製基類簽名,或從其他地方提供參數,都取決於您想要完成的工作。
如果在派生自BaseClass的類中實現__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__
來解決這個問題。
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__
,這是傳遞給__init__
方法Bar
的Bar
實例。由於Bar
繼承自Foo
,所以Bar
的實例也是Foo
的實例,因此允許將self
傳遞給Foo.__init__
。
很有可能是您繼承的類需要或接受的參數多於類的實例。這將打印20
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()
:這些,你會與你從__init__
內調用的任何方法處理。
如果您試圖通過繼承類來實現完全公開基類的所有初始化參數的接口,則需要明確地執行此操作。這通常是通過* 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__
。然後將第二個參數合併到變量args
和kwargs
中(*和**是特定的語法,表示在傳遞給函數/方法時將列表/元組或字典擴展爲單獨的參數),並傳遞給Foo.__init__
。
這個例子也使得任何覆蓋方法需要顯式調用,如果這是需要什麼(如do_something
在這種情況下)的地步。
最後一點,您將經常看到super(ChildClass, self).method()
(其中ChildClass
是某些任意子類),而不是顯式調用BaseClass
方法。關於super
的討論是另外一個問題,但足以說明,在這些情況下,通常通過調用BaseClass.method(self)
來完成正在完成的工作。簡而言之,super
以方法解析順序將方法調用委託給下一個類 - MRO(在單一繼承中是父類)。有關更多信息,請參見documentation on super。
- 1. 派生類使用基類的屬性?
- 2. XmlInclude屬性和派生類
- 3. C#給定的基類,派生類的更新基類屬性
- 4. XMLPull - 基類和派生類
- 5. 基類和派生類
- 6. 使用在基類派生類,而派生類的基類
- 7. 屬性返回派生類
- 8. 從C#中的基類訪問派生類的屬性#
- 9. Python繼承 - 從基類到派生類
- 10. `Activator.CreateInstance`和派生類型`new`屬性
- 11. 派生類沒有基類屬性的值
- 12. 使用基類反映派生類中的屬性
- 13. 用派生類替代基類的屬性
- 14. 如何讓派生類使用基類的屬性?
- 15. 如何在派生類中引用基類的屬性?
- 16. Qt - 派生類是否繼承其基類的元屬性?
- 17. 從基類實現派生類的自動屬性?
- 18. 設置基類屬性使用派生類的構造函數
- 19. AutoMapper將派生類映射到基類型集合的屬性
- 20. 實現基類方法來訪問派生類的屬性
- 21. 序列化派生類型派生類型屬性的數組
- 22. C++基類和派生類的限制
- 23. 包中的基類和派生類
- 24. NHibernate的基類和派生類映射
- 25. 基礎和派生類C++
- 26. 基地和派生類
- 27. 空派生類與Vs類型屬性
- 28. 如何查找派生類型隱藏其屬性的基類屬性
- 29. Python - 重新定義派生類中的類屬性
- 30. 從派生類c訪問基類(列表)屬性#