Python全棧開發之面向對象

No.1 概念

面向對象的特色?

注重對象和指責,不一樣的對象承擔各自的指責算法

更加適合對複雜的需求變化,專門應對複雜項目開發,提供固定的套路編程

面向對象強調的是誰來作,面向過程強調的如何作app

什麼是類

類是對一羣具備相同特徵或者行爲的事物統稱,是抽象的,不能直接使用,特徵被稱爲屬性,行爲被稱爲方法,類就是一個模板ide

什麼是對象

對象是由類建立出來的一個具體存在,能夠直接使用,經過哪一個類建立出來的實例,就擁有哪一個類中定義的特徵和行爲函數

類和對象的關係

類是模板,對象是根據類這個模板建立出來的,先有類,再有對象code

類只有一個,對象有多個對象

類中定義的方法屬性都會存在對象中,很少很多繼承

不一樣的對象之間的屬性不盡相同內存

No.2 類的建立

方法名 類型 做用
new 方法 經過類()建立對象時,向內存申請空間,並將對象引用傳遞給init
init 方法 對象初始化時,會調用此方法
del 方法 對象被銷燬時,會調用此方法
str 方法 返回對象的描述信息
class Cat:
    """這是一個貓類"""

    def eat(self):
        print("小貓愛吃魚")

    def drink(self):
        print("小貓在喝水")

tom = Cat()
tom.drink()
tom.eat()

對象中的self參數開發

在類封裝的方法內部,self就表示當前調用方法的對象本身
調用方法時,不須要傳遞self參數
在方法內部能夠經過self.訪問對象的屬性
也能夠經過self.調用其餘的對象方法
class Cat:
    def __init(self,name)
        self.name = name

    def eat(self):
        print("%s 愛吃魚" % self.name)

tom = Cat('mimimi')
tom.eat()

No.3 封裝

封裝是面向對象編程的一大特色

面向對象將屬性和方法封裝到一個抽象的類中

外部使用類建立對象,而後讓對象調用方法

對象方法的細節都被定義到類的內部

No.4 繼承

DFS(深度優先算法):

class E:
    def say(self):
        print('E')
class D:
    pass
class C(E):
    pass
class B(D):
    pass
class A(B,C):
    pass
a = A()
a.say()
# 查找順序 A->B->D->C->E

BFS(廣度優先算法):

class E:
    def say(self):
        print('E')
class D:
    pass
class C(E):
    pass
class B(D):
    pass
class A(B,C):
    pass
a = A()
a.say()
# 查找順序 A->B->C->D->E

C3(算法):

class F:
    def say(self):
        print('F')
class E(F):
    pass
class D(F):
    pass
class C(E):
    pass
class B(D):
    pass
class A(B,C):
    pass
a = A()
a.say()
print(A.__mro__) # (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <class 'object'>)
# 查找順序 A->B-?>D-C->E-F

No.5 多態

Python中不支持多態,也不用支持多態,Python是一種多態語言,崇尚鴨子類型,鴨子類型的概念來自於:「當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就能夠被稱爲鴨子,Python不會檢查類型是否是鴨子,只要它擁有鴨子的特徵,就能夠被正確的調用

class Duck:
    def speak(self):
        print('嘎嘎嘎...')
class Dog:
    def speak(self):
        print('汪汪汪...')
class Cat:
    def speak(self):
        print('喵喵喵...')
animal = []
animal.append(Duck)
animal.append(Dog)
animal.append(Cat)
for i in animal:
    i().speak()
# 嘎嘎嘎...
# 汪汪汪...
# 喵喵喵...

No.6 類方法、靜態方法、實例方法

實例方法第一個參數必須是self,經過實例方法來傳遞實例的屬性和方法,只能同實例來調用,靜態方法使@staticmethod裝飾器來定義,參數隨意,靜態方法是一個獨立的函數,它僅僅依託於類的命名空間,不會涉及到類是屬性和方法的做,靜態方法由於沒有參數綁定到該類因此僅僅提供函數功能,不能調用實例屬性或靜態屬性,類方法使用@classsmethod來定義,第一個參數必須是cls,經過它傳遞類的屬性和方法,類方法只能調用靜態屬性

class Data():
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day
    @staticmethod
    def static_method(date_str):
        year,month,day = tuple(date_str.split('-'))
        return Data(int(year),int(month),int(day))
    @classmethod
    def class_method(cls,date_str):
        year, month, day = tuple(date_str.split('-'))
        return cls(int(year), int(month), int(day))
    def object_method(self):
        print(self.year,self.month,self.day,sep='-')
if __name__ == '__main__':
    date = Data(2018,9,15)
    date.object_method() # 2018-9-15
    date = Data.class_method('2018-9-16')
    date.object_method() # 2018-9-16
    date = Data.static_method("2018-9-17")
    date.object_method() # 2018-9-17

No.7 類變量和實例變量

類變量,能夠經過類調用,也能夠經過實例調用,在內存中之存在一份

實例變量,只能經過實例調用,每一個對象都有一份

class Person:
    country = "中國"
    def __init__(self,name,age):
        self.name = name
        self.age = age

p1 = Person('kernel',18)
print(p1.name) # kernel
print(p1.age) # 18
print(p1.country) # 中國
print(Person.country) # 中國
p1.country = "美國" # 當經過對象修改類變量時,將會在該對象建立一個和類變量同名的變量,類變量依然不變
print(p1.country) # 美國
print(Person.country) # 中國
p2 = Person('alex',38)
print(p2.name) # alex
print(p2.age) # 38
print(p2.country) # 中國

No.8 私有屬性和數據封裝

class User:
    def __init__(self,name,age):
        self.name = name
        self.__age = age
    def get_age(self):
        print(self.__age)
    def set_age(self,age):
        self.__age = age
if __name__ == '__main__':
    u = User('kernel',18)
    # print(u.__age) # AttributeError: 'User' object has no attribute '__age' 好吧,私有屬性不讓我訪問,可是真的沒法訪問嗎
    print(u._User__age) # 但這又是什麼鬼呢?固然咱們不建議這麼幹
    u.set_age(19) 
    u._User__age=20 # 固然,設置也能夠這樣
    u.get_age() # 20

No.9 單例模式

new方法

使用類名()建立對象,首先會調用new方法爲對象分配空間,它的主要做用就是在內存中爲對象分配空間和返回對象的引用,Python解釋器獲得對象的引用後,將引用傳遞給init

讓類建立的對象,在系統中只有惟一的一個實例

定義一個類屬性,初始值是None,用於記錄單例對象的引用

重寫new方法

若是類屬性是None,調用方法申請空間,並在類屬性中記錄

返回類屬性中紀錄的對象引用

class MusicPlayer(object):
    instance = None # 記錄第一個被建立對象的引用
    init_flag = False # 記錄是否執行過初始化動做

    def __new__(cls, *args, **kwargs):
        if cls.instance is None:#  判斷類屬性是不是空對象
            cls.instance = super().__new__(cls)  #  調用父類的方法,爲第一個對象分配空間
        return cls.instance # 返回類屬性保存的對象引用

    def __init__(self):
        if not MusicPlayer.init_flag:
            MusicPlayer.init_flag = True

player1 = MusicPlayer() # <__main__.MusicPlayer object at 0x0000017C297F99E8>
print(player1)
player2 = MusicPlayer() # <__main__.MusicPlayer object at 0x0000017C297F99E8>
print(player2)
相關文章
相關標籤/搜索