今天要學習的是面向對象,Python從設計之初就已是一門面向對象的語言,正由於如此,在Python中建立一個類和對象是很容易的,咱們先一塊兒來看一下類和對象的定義~html
class 類的名稱: 語句塊 # 舉例說明 class Student: num = 100 def showNum(self): return 200 print(Student.num) # 輸出:100 print(Student.showNum) # 輸出:<function Student.showNum at 0x009A9468> # Student就是類對象,num是類變量,showNum是方法,self爲類對象的實例, 類名稱通常須要大寫
講完類和對象,咱們來看一下實例,類是抽象的模板,而實例是根據類建立出來的一個個具體的「對象」,每一個對象都擁有相同的方法,但各自的屬性可能不一樣;python
class Student: def prt(self): print(self) print(self.__class__) s = Student() s.prt() # 執行結果: # <__main__.Student object at 0x0000000001D7CDA0> # <class '__main__.Student'>
上述例子中self
表明的是類的實例,而self.__class__
指向類,且self 不是 python 關鍵字,咱們把self換成其它的單詞也能夠正常運行;設計模式
咱們知道了什麼是實例,那實例化又是什麼呢,接着看下面這個例子,在Student類中有兩個方法,一個是初始化方法__init__
,另外一個是我本身定義的方法showClass()方法數據結構
class Student: num = 100 def __init__(self): self.name = '張三' def show(self): return '李四' print(Student.num) # 輸出:100 print(Student.show) 輸出:<function Student.show at 0x0000000002765BF8> stu = Student() # 這就是實例化,且實例化會自定調用__init__方法,self會自動傳遞,不能有return返回值 print(stu.name) # 張三
__init__()
方法,能夠用它來爲每一個實例定製本身的特徵(屬性);init()
方法被稱爲類的構造函數或初始化方法,須要注意的是__init__()
方法不能有return返回值;而後咱們來說一下什麼是類變量和實例變量,看看這二者之間有什麼不一樣;函數
# 實例變量是實例特有的,類變量是類和實例共有的 class Student: num = 100 def __init__(self, name): self.name = name def showClass(self): return 200 print(Student.num) print(Student.showClass) stu = Student('張三') # 實例化,會調用__init__方法,self會自動傳遞,不能有return返回值 print(stu.name) # 實例變量 print(stu.num) # 類變量
直接看這個實例可能還不太直觀,你們本身在程序裏面動手運行一下,使用Student類調用num和name兩個變量,就會發如今調用num的時候能正常輸出,而調用name的時候報錯了。而後再用實例對象stu調用這兩個變量試試,咱們就能得出下面兩個結論:性能
講完了類變量和實例變量,那咱們來看一下類方法和實例方法:學習
class Student: num = 100 def __init__(self, name): self.name = name def showClass(self): return '張三' @classmethod def add(cls): print(cls) stu = Student('張三') # 實例化,會調用__init__方法,self會自動傳遞,不能有return返回值 print(stu.name) # 實例變量 輸出:張三 print(stu.num) # 類變量 輸出: 100 print(stu.__dict__) # 類的屬性保存在本身的字典中,包括類變量和方法 print(stu.__dict__) # 實例的屬性保存在本身的字典中,包括實例的變量 stu.add() # 類方法能夠被實例對象調用 輸出:<class '__main__.Student'> stu.__class__.add() print(Student.showClass()) # 報錯,實例方法不能夠被類對象調用 print(Student.name) # 實例能夠訪問類的屬性,類沒法訪問實例的屬性
咱們動手試一下,分別用Student類,和實例對象stu來調用類方法和實例方法,咱們就能得出一下結論:測試
除了類方法和實例方法以外,還有一個方法叫作靜態方法,咱們一塊兒來看一下靜態方法如何使用:編碼
class Student: def __init__(self, name): self.name = name @staticmethod def sub(): print('static') stu = Student('李四') stu.sub() # 實例能夠調用靜態方法 輸出:static Student.sub() # 類能夠調用靜態方法 輸出:static
而後咱們能夠得出一下兩個結論:設計
__
開頭的屬性爲私有屬性,不能在類的外部被使用或直接訪問;_
開頭的爲保護屬性,只有類實例和子類實例能訪問,需經過類提供的接口進行訪問;咱們來看一下私有屬性和保護屬性是如何使用的:
class Student(object): def __init__(self): self.__private_field = 200 # private self._protect_field = 200 # protect stu = Student() # print(stu.__private_field) # 報錯,實例對象不能夠調用私有屬性 print(stu._protect_field) # 輸出:200
class Student: num = 100 def __init__(self, name): self.__name = name @property def name(self): return self.__name @name.setter def name(self, name): self.__name = name @name.deleter def name(self): del self.__name stu = Student('張三') print(stu.name) # 輸出:張三 stu.name = '李四' print(stu.name) # 輸出:李四
class Student: def __init__(self, name): self.__name = name def get_name(self): return self.__name def set_name(self, value): self.__name = value def del_name(self): del self.__name print('實例的屬性被刪除了') # 這裏表示property是用來修飾name這個屬性的 name = property(fget=get_name, fset=set_name, fdel=del_name, doc='hello') stu = Student('張三') print(stu.name) # 張三 stu.name = '李四' # 給name賦值 print(stu.name) # 李四
class Animal: def __init__(self): self.type = 'animals' def eat(self): print('{} 吃,Animal類中'.format(self.__class__.__name__)) # Animal 吃,Animal類中 class Person(Animal): def talk(self): print('講話') # animal = Animal() # animal.eat() # # print(animal.type) # animals # animal.talk() # 報錯,父類不能夠調用子類的方法 person = Person() print(person.type) # animals # Person調用Animal類的eat方法 person.eat() # 輸出:Person 吃,Animal類中 person.talk() # 講話
class Animal: __name = 'animal' def __init__(self): self.type = 'animal' def eat(self): print('{} eat'.format(self.__class__.__name__)) class Person(Animal): def talk(self): print('talk') person = Person() print(person.__name) # 子類不能訪問 父類的私有屬性
__dict__
中查找->而後從對象所在類的__dict__
中查找->而後從父類的__dict__
中查找,直至找到或者報錯沒有找到;class Animal: def __init__(self): self.type = 'animal' def eat(self): print('{} eat'.format(self.__class__.__name__)) class Person(Animal): def eat(self): print('洗手') # 洗手 print('{} eat'.format(self.__class__.__name__)) # Person eat super().eat() # 調用父類的方法 # Person eat # super(Person, self).eat() 等價於 super().eat() person = Person() person.eat()
class Animal: def __init__(self): self.one = 'one' class Person(Animal): def __init__(self): self.two = 'two' self.three = 'three' def show(self): print(self.one, self.two, self.three) person = Person() print(person.__dict__) # 輸出:{'two': 'two', 'three': 'three'} person.show() # 報錯,person沒有one這個屬性 print(person.one) #一樣報錯
class Animal: def __init__(self): self.one = 'one' class Person(Animal): def __init__(self): self.two = 'two' self.three = 'three' super().__init__() # 繼承父類的__init__方法,且父類init方法的調用寫在子類的什麼地方也有講究 def show(self): print(self.one, self.two, self.three) person = Person() print(person.__dict__) print(person.one) # 輸出:one ,由於繼承了父類的init__方法,因此能夠訪問one屬性
super()
函數是用於調用父類(超類)的一個方法, Python 3 可使用直接使用super().xxx 代替 super(Class, self).xxx
;__init__
方法,由於Mixin類不作爲獨立類使用;