注重對象和指責,不一樣的對象承擔各自的指責算法
更加適合對複雜的需求變化,專門應對複雜項目開發,提供固定的套路編程
面向對象強調的是誰來作,面向過程強調的如何作app
類是對一羣具備相同特徵或者行爲的事物統稱,是抽象的,不能直接使用,特徵被稱爲屬性,行爲被稱爲方法,類就是一個模板ide
對象是由類建立出來的一個具體存在,能夠直接使用,經過哪一個類建立出來的實例,就擁有哪一個類中定義的特徵和行爲函數
類是模板,對象是根據類這個模板建立出來的,先有類,再有對象code
類只有一個,對象有多個對象
類中定義的方法屬性都會存在對象中,很少很多繼承
不一樣的對象之間的屬性不盡相同內存
方法名 | 類型 | 做用 |
---|---|---|
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()
封裝是面向對象編程的一大特色
面向對象將屬性和方法封裝到一個抽象的類中
外部使用類建立對象,而後讓對象調用方法
對象方法的細節都被定義到類的內部
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
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() # 嘎嘎嘎... # 汪汪汪... # 喵喵喵...
實例方法第一個參數必須是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
類變量,能夠經過類調用,也能夠經過實例調用,在內存中之存在一份
實例變量,只能經過實例調用,每一個對象都有一份
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) # 中國
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
使用類名()建立對象,首先會調用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)