繼承
雖然子類Bosi沒有__init__()方法,但是父類有,所以子類在繼承父類時,這個方法也被繼承了。所以只要創建了Bosi的對象,就默認執行繼承過來的__init__()方法。
子類在繼承的時候,在定義類的時候,小括號()中為父類的名字,父類的屬性、方法都會繼承給子類。
當子類和父類擁有同一方法是,調用誰的方法。觀察如下代碼:
子類和父類同有__init__()方法,在對象調用時,子類的__init__()方法會覆蓋父類的__init__()方法。
關于對象調用時的地址和繼承調用時的地址,觀察如下代碼:
可以看出,他們的地址是一樣的。
私有的屬性和方法都不能被繼承,也不能被對象直接調用,可以通過方法訪問。一般情況下,私有的屬性和方法都是不對外公布的,往往用來做內部的事情,起到安全的作用。
一個子類不僅可以單一繼承,也可以多繼承。當一個子類有多個父類時,具體的操作代碼如下:
從以上的例子可以看出,當存在多個父類時,且這些父類擁有同名的方法,子類會按照繼承的順序去調用方法,而不會發生父類方法的重寫。
如果想子類父類都有該方法,如何重寫子類覆蓋的父類方法,方式有兩種。具體代碼如下:
使用super().父類方法名()可以實現重寫父類方法,但因為是按繼承順序調用的父類方法,所以父類F2()中的test ()方法不會被調用。如何在不修改繼承順序的情況下調用父類F2()中的test ()方法。代碼如下:
通過父類名.父類方法名(self)可以實現想要訪問的父類方法。
對于屬性的賦值,如果在子類中對特殊屬性賦值時,將會覆蓋父類對于共有屬性的定義,所以可以采用以上的方法對屬性賦值:
通過以上代碼,不僅完成了對Dog()這一類特殊屬性的賦值,也完成了父類Animal()的通用屬性的賦值。
類屬性、實例屬性
class?Student():
name?=?'Tony'
__age?=?18
stu1?=?Student()
print(stu1.name)輸出Tony
print(Student.name)輸出Tony
print(stu1.__age)報錯,不能在類外通過實例對象訪問私有的類屬性
print(Student.__age)報錯,不能在類外通過類對象訪問私有的類屬性
class?People(object):
#類屬性
address?=?'山東'
def?__init__(self):
self.name?=?'xiaowang'
self.age?=?20
p?=?People()
p.age?=12
print(p.address)
print(p.name)
print(p.age)
print(People.address)
print(People.name)
print(People.age)
輸出結果如上所示。如何通過實例對象修改類屬性?
如果需要在類外修改類屬性,必須通過類對象去引用然后進行修改。如果通過實例對象去引用,會產生一個同名的實例屬性,這種方式修改的是實例屬性,不會影響到類屬性,并且之后如果通過實例對象去引用該名稱的屬性,實例屬性會強制屏蔽掉類屬性,即引用的是實例屬性,除非刪除了該實例屬性。
類方法
是類對象所擁有的方法,需要用修飾器@classmethod來標識其為類方法,對于類方法,第一個參數必須是類對象,一般以cls作為第一個參數(當然可以用其他名稱的變量作為其第一個參數,但是大部分人都習慣以'cls'作為第一個參數的名字,就最好用'cls'了),能夠通過實例對象和類對象去訪問。
class?People(object):
country?=?'china'
#類方法,用classmethod來進行修飾
@classmethod
def?getCountry(cls):
return?cls.country
p?=?People()
print(p.getCountry())#可以用過實例對象引用
print(People.getCountry())????#可以通過類對象引用
類方法還可以對類屬性進行修改
class?People(object):
country?=?'china'
#類方法,用classmethod來進行修飾
@classmethod
def?getCountry(cls):
return?cls.country
@classmethod
def?setCountry(cls,country):
cls.country?=?country
p?=?People()
print(p.getCountry())?????????#可以用過實例對象引用
print(People.getCountry())????#可以通過類對象引用
p.setCountry('japan')
print(p.getCountry())
print(People.getCountry())
靜態方法
需要通過修飾器@staticmethod來進行修飾,靜態方法不需要多定義參數
class?People(object):
country?=?'china'
@staticmethod
#靜態方法
def?getCountry():
return?People.country
print(People.getCountry())
從類方法和實例方法以及靜態方法的定義形式就可以看出來,類方法的第一個參數是類對象cls,那么通過cls引用的必定是類對象的屬性和方法;而實例方法的第一個參數是實例對象self,那么通過self引用的可能是類屬性、也有可能是實例屬性(這個需要具體分析),不過在存在相同名稱的類屬性和實例屬性的情況下,實例屬性優先級更高。靜態方法中不需要額外定義參數,因此在靜態方法中引用類屬性的話,必須通過類對象來引用。