Python面向對象三大特性

Python是面向對象的語言,也支持面向對象編程的三大特性封裝(隱藏)、繼承、多態。

一、封裝(隱藏):

隱藏對象的屬性和實現細節,只對外提供必要的方法。相當於將"細節封裝起來",只對外暴露“相關調用方法”。通過私有屬性私有方法的方式實現封裝。Python追求簡潔的語法,沒有嚴格的語法級別的"訪問控制符",更多的是依靠程序員的自覺實現。

二、繼承:

如果一個新類繼承自一個設計好的類,就直接具備了已有類的特徵,就大大降低了工作難度,已有的類,我們稱爲"父類或基類",新的類,我們稱爲“子類或派生類”。

繼承可以讓子類具有父類的特性,提高了代碼的重用性。

Python支持多重繼承一個子類可以繼承多個父類,繼承的語法格式如下:

class  子類類名(父類1,父類2,…):
    類體

如果在類定義中沒有指定父類,則默認父類是object類,也就是說object類是所有類的父類,因此所有類都有object類的屬性和方法,object類裏面定義了一些所有類共有的默認實現,比如__init()__,_new__()。

定義子類時,必須在其構造函數中調用父類的構造函數(此處只是邏輯上的必須,語法上沒有嚴格要求,但是一般要調),調用格式如下:

父類名.__init__(self,參數列表)

#測試繼承的基本使用
class Person:
    def __init__(self,name,age):  #屬性在構造器中
        self.name=name
        self.__age=age  #私有屬性(子類可以調用,但是不能用,也就是說子類繼承了父類所有的屬性方法,但是父類私有的屬性方法子類不能用)
    def say_age(self):
        print("嘿嘿,不告訴你")
class Student(Person):
    def __init__(self,name,age,score):
        Person.__init__(self,name,age)#必須顯式的調用父類初始化方法,不然解釋器不會去調用
        self.score=score
# Student——>Person——>object類
print(Student.mro())#查看類的繼承層次結構
s=Student("張無忌","18","100")
s.say_age()
print(s.name)
# print(s.age)  父類的私有屬性,子類不能用
print(dir(s))
print(s._Person__age)#實例對象._類名__私有屬性  這樣纔可以用(這說明Python中並沒有完全意義上的私有,需靠程序員的自覺性去維護)
如果在子類中需要父類的構造方法就需要顯式的調用父類的構造方法,或者重寫父類的構造方法。
如果子類不重寫 __init__,實例化子類時,會自動調用父類定義的 __init__
如果重寫了__init__ 時,實例化子類,就不會調用父類已經定義的 __init__
如果重寫了__init__ 時,要繼承父類的構造方法,可以使用 super 關鍵字

類成員的繼承和重寫:

1.成員繼承:子類繼承了父類除構造方法之外的所有成員。

2.方法重寫:子類可以重新定義父類中的方法,這樣就會覆蓋父類中的方法,也稱爲重寫。

class Person:
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    def say_age(self):
        print("我的年齡是",self.__age)
    def say_introduce(self):
        print("我的名字是{}".format(self.name))
class Student(Person):
    def __init__(self,name,age,score):
        Person.__init__(self,name,age)
        self.score=score
    def say_introduce(self):
        '''重寫了父類的方法'''
        print("報告老師,我的名字是{}".format(self.name))
s=Student("張無忌",18,100)
s.say_age()
s.say_introduce()

#打印結果
我的年齡是 18
報告老師,我的名字是張無忌

通過類的方法mro()或者類的屬性_mro_可以輸出這個類的繼承層次結構。

通過類的方法dir()查看對象屬性

class A:
    pass
class B(A):
    pass
class C(B):
    pass
#mro()查看類的繼承層次結構
print(C.mro())   #或者用 print(C.__mro__)
#dir()查看對象屬性
a=A()
print(dir(a))

#結果如下:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

重寫_str_方法:

用於返回一個對於“對象的描述”,對應於內置函數str()經常用於print()方法,幫助我們查看對象的信息。_str_()可以重寫。

class Person():
    def __init__(self,name):
        self.name=name

p=Person("張三丰")
print(p)

#打印結果如下:  object類中__str__()的默認實現,打印類的信息
<__main__.Person object at 0x03110D30>

_str_()重寫後

class Person():
    def __init__(self,name):
        self.name=name
    def __str__(self):
        return "名字是:{}".format(self.name)
p=Person("張三丰")
print(p)
#打印結果如下:
名字是:張三丰

關於多重繼承:

Python支持多重繼承,一個子類可以有多個“直接父類”,這樣就具備了多個父類的特點,但是由於這樣會把“類的整體層次”搞得很複雜,儘量避免使用

#測試多重繼承
class A:
    def aa(self):
        print("aa")
class B:
    def bb(self):
        print("bb")
class C(A,[B]):
    def cc(self):
        print("cc")

c=C()
#打印結果:
c.aa()
c.bb()
c.cc()

 

mro()

Python支持多繼承,如果父類中有相同名字的方法,在子類沒有指定父類名時,解釋器將“從左向右”按順序搜索。

MRO(Method Resolution Order):方法解析順序,我們可以通過mro()方法獲得“類的層次結構”,方法解析順序也是按照這個“類的層次結構”尋找到。

class A:
    def aa(self):
        print("aa")
    def say(self):
        print("say AAA!")
class B:
    def bb(self):
        print("bb")
    def say(self):
        print("say BBB!")
class C(A,B):
    def cc(self):
        print("cc")

c=C()
print(C.mro())
c.say()  #解釋器尋找方法是"從左到右的順序"尋找,此時會執行A類中的say()
#打印結果
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
say AAA!

super()獲得父類定義

在子類中,如果想要獲得父類的方法時,我們可以通過super()來做,super()代表父類的定義,而不是父類對象。

#測試super()代表和父類有關,而不是父類對象!
class A:
    def say(self):
        print("A:",self)
class B(A):
    def say(self):
        # A.say(self) 也可調用
        super().say()  #()中沒有傳self說明調用的是類方法,()中傳self說明調用的是類的實例化方法
        print("B:",self)
B().say()

 

三、多態:

多態(polymorphism)是指同一個方法調用,由於對象不同可能會產生不同的行爲。

注意:

1.多態是方法的多態,屬性沒有多態

2.多態的存在有兩個必要條件:繼承、方法重寫

 

class Man:
    def eat(self):
        print("餓了,吃飯了!")
class Chinese(Man):
    def eat(self):
        print("中國人用筷子吃飯")

class English(Man):
    def eat(self):
        print("英國人用刀叉吃飯")

class Indian(Man):
    def eat(self):
        print("印度人用右手吃飯")


def manEat(m):
    if isinstance(m,Man):
        m.eat()
    else:
        print("不能吃飯")

manEat(Chinese())
manEat(English())

#運行結果
中國人用筷子吃飯
英國人用刀叉吃飯
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章