1.什麼叫類: 類是一種數據結構, 就比如一個模型, 該模型用來表述一類事務(事務即數據和動做的結合體), 用它來生產真實的物體(實例).python
2.什麼叫對象: 睜開眼, 你看到的一切的事物都是一個個的對象, 你能夠把對象理解爲一個具體的事物(事物即數據和動做的結合體)算法
3.類與對象的關係: 對象都是由類產生的編程
4.什麼叫實例化:由類生產對象的過程叫實例化,類實例化的結果就是一個對象,或者叫作一個實例(實例=對象)數據結構
面向對象設計:將一類具體事物的數據和動做整合到一塊兒,即面向對象設計socket
#用基於結構化的語言來實現面向對象設計 def wang(name,genle,type): def jiao(dog): print("%s正在叫"%dog["name"]) def chi(dog): print("%s正在吃"%dog["name"]) def init(name,genle,type): dog1 ={ "name":name, "genle":genle, "type":type, "jiaoa":jiao, "chi":chi } return dog1 return init(name,genle,type) d1 = wang("xiaoming","gong","tianyuanquan") print(d1) d1["jiaoa"](d1)
面向對象編程: 用定義類 + 實例/對象的方式去實現面向對象的設計函數
class Chinese: name = "abc" def chifan(self,x): print("姓名:%s喜歡吃%s"%(self.mingzi,x)) def shuijiao(self): print("nianling:%s"%self.nianling) def __init__(self,name,age): self.mingzi = name self.nianling = age f1 = Chinese("xiaoming",18) f1.chifan("eat") f1.shuijiao()
1 大前提: 2 1.只有在python2中才分新式類和經典類,python3中統一都是新式類 3 2.新式類和經典類聲明的最大不一樣在於,全部新式類必須繼承至少一個父類 4 3.全部類甭管是否顯式聲明父類,都有一個默認繼承object父類(講繼承時會講,先記住) 5 在python2中的區分 6 經典類: 7 class 類名: 8 pass 9 10 經典類: 11 class 類名(父類): 12 pass 13 14 在python3中,上述兩種定義方式全都是新式類
python3中聲明類
1 ''' 2 class 類名: 3 '類的文檔字符串' 4 類體 5 ''' 6 7 #咱們建立一個類 8 class Data: 9 pass 10 11 #用類Data實例化出一個對象d1 12 d1=Data()
類有數據屬性跟函數屬性(又稱方法屬性)ui
class Chinese: name = "abc" def chifan(self,x): print("姓名:%s喜歡吃%s"%(self.mingzi,x)) def shuijiao(self): print("nianling:%s"%self.nianling) def __init__(self,name,age):#爲實例定製數據屬性,可使用類的一個內置方法__init__()該方法,在類()實例化是會自動執行 self.mingzi = name self.nianling = age f1 = Chinese("alex",18) #類的實例化,至關於運行__init__函數,將參數傳給__init函數體中對應的位置,生成一個字典,其中self即表明f1自身 f1.chifan("eat")#經過.調用類的屬性,首先會在__init__做用域內查找,若沒找到會到類的屬性中尋找,實例化生成的對象只具有數據屬性,調用的方法爲類的屬性並不是生成的對象所具有的屬性 f1.shuijiao()
有兩種方法查看類的屬性spa
dir(類名): 查出的是一個名字列表設計
類名.__dict__:查出的是一個字典, key爲屬性名, value爲屬性值code
1 class Chinese: 2 name = "abc" 3 def chifan(self): 4 print(123) 5 def shuijiao(self): 6 print("456") 7 print(Chinese.name)#打印的是name屬性對應的內容 8 print(Chinese.__dict__)#顯示結果是一個字典,包含類的全部屬性:屬性值 9 print(dir(Chinese))#顯示結果是一個列表,包含類(包含內建屬性在內的)全部的屬性名
特殊的類屬性
__name__,類的名字
__doc__,查看類的文檔字符串
__module__, 類定義所在的模塊__class__, 實例C對應的類(僅新式類中)
類的方法屬性的增刪改查
1 class math: 2 country = "China" 3 def chi(self,food): 4 print("%s正在吃%s"%(self.mingzi,food)) 5 def __init__(self,name): 6 self.mingzi = name 7 f1 = math("alex") 8 print(math.country) #查看 9 # print(dir(math)) 10 # print(math.__dict__) 11 def yundong(self,hobby):#增長 12 print("%s正在%s"%(self.mingzi,hobby)) 13 math.aihao = yundong 14 #print(math.__dict__) 15 f1.aihao("打籃球") 16 #del math.chi 17 #print(math.__dict__) 18 def aichi(self,food):#修改 19 print("%s很開心的吃%s"%(self.mingzi,food)) 20 math.chi =aichi 21 f1.chi("面")
1 class math: 2 country = "China" 3 def chi(self,food): 4 print("%s正在吃%s"%(self.mingzi,food)) 5 def __init__(self,name,age): 6 self.mingzi = name 7 self.nianling = age 8 9 f1 = math("xiaoming",18) 10 print(f1.__dict__) #查看 11 f1.mingzi = "eric" #修改 12 print(f1.__dict__) 13 f1.xingbie = "男" # 增長 14 del f1.mingzi #刪除 15 print(f1.__dict__)
1.實例化會自動觸發__init__函數的運行,最後返回一個值即實例, 咱們要找的實例屬性就存放 在 __init__函數的局部做用域裏
2.類有類的屬性字典, 就是類的做用域, 實例有實例的屬性字典, 即實例的做用域
3.綜上, 一個點表明一層做用域, obj.x先從本身的做用域找, 本身找不到去外層的類的字典中去 找, 都找不到, 就會報錯
4.在類中沒有使用點的調用, 表明調用全局變量
1 country = "China" 2 class Chinese: 3 country = "japan" 4 def __init__(self,name): 5 self.mingzi = name 6 print(country)#打印的是普通變量country,非類結構中的變量,要調用類中的變量要用"."調用 7 f1 = Chinese("tom")
1 class Room: 2 arg = 123 3 def __init__(self,name,weith,lenth,height): 4 self.mingzi = name 5 self.kuandu = weith 6 self.changdu = lenth 7 self.gaodu = height 8 @property#靜態屬性,將實例化對象變成類的數據屬性,將該方法封裝起來,做用可隱藏邏輯代碼,直接用實例+"."調用該方法 9 def tiji(self): 10 return self.kuandu*self.changdu*self.gaodu 11 12 @classmethod#類方法,專門供類使用,與實例無關,類方法只能訪問類相關的屬性,不能訪問實例屬性,與實例無關 13 def tell_info(cls,x):#默認參數cls不可變,爲類名,後邊可接參數 14 print(cls) 15 print("------>",Room.arg,x) 16 17 @staticmethod #靜態方法 ,類的靜態方法,沒有默認參數,不能使用類變量和實例變量 18 def op(x,y,z): 19 print(x,y,z) 20 f1 = Room("tom",10,50,20) 21 print(f1.tiji)#因爲用了property方法封裝該方法(已變成數據屬性),故可直接調用該數據屬性 22 Room.tell_info("abc") 23 Room.op(1,2,3) #類傳參數能夠調用 24 f1.op(1,2,3) #實例傳參數能夠調用
做用: 作關聯
1 class School: 2 def __init__(self,name,difang): 3 self.name = name 4 self.difang = difang 5 class Teacher: 6 def __init__(self,name,sex,school): 7 self.name = name 8 self.sex = sex 9 self.school = school 10 class Lesson: 11 def __init__(self,name,price,period,techer): 12 self.name = name 13 self.price = price 14 self.period = period 15 self.techer = techer 16 17 p1 = School("baidu","北京") 18 t1 = Teacher("tom","male",p1)#將p1對象直接添加到t1對象屬性中 19 L1 = Lesson("python班",10000,"4month",t1)
python中類的繼承分爲: 單繼承和多繼承
class ParentClass1: pass class ParentClass2: pass class SubClass(ParentClass1): #單繼承 pass class SubClass(ParentClass1,ParentClass2): #多繼承 pass
子類繼承了基類的全部屬性
class Dad: money = 10 def __init__(self,name): self.name = name def hit_son(self): print("打人") class Son(Dad):#繼承參數「類」的全部屬性 money = 5000#當子級類屬性跟父級類屬性重名時,調用當級類方法會先從當級尋找,找不到會去父級找 pass p1 = Son("eric") print(p1.name) p1.hit_son() print(p1.money)
當類之間有顯著的不一樣, 而且較小的類是較大的類所須要的組件時, 用組合比較好
當類之間有不少相同的功能, 提取這些共同的功能作成基類, 用繼承比較好
含義一:繼承基類的方法, 而且作出本身的改變或者擴展 (代碼重用)
含義二:聲明某個子類兼容於某基類, 定義一個接口類, 子類繼承接口類, 而且實現接口中定 義的方法
接口繼承 import abc #調用接口繼承模塊 class All_file(metaclass=abc.ABCMeta):#聲明某個子類兼容於某基類,定義一個接口類,子類繼承接口類,而且實現接口中定義的方法 @abc.abstractclassmethod #裝飾器使方法具有接口繼承特性 def read(self): pass @abc.abstractclassmethod def write(self): pass class Disk(All_file):#子類繼承基類時,必須對基類的方法進行派生纔可實例化 def read(self): print("disk-read") def write(self): print("disk-write") class Cd(All_file): def read(self): print("cd-read") def write(self): print("cd-write") class Mem(All_file): def read(self): print("mem-read") def write(self): print("mem-write") p1 = Disk() p1.read()
當類是經典類時, 多繼承狀況下, 會按照深度優先方式查找
當類是新式類時, 多繼承狀況下, 會按照廣度優先方式查找
經典類與新式類的差異: 新式類在定義時便自動繼承了object類, 而經典類沒有
新式類繼承順序: 對於你定義的每個類, python會計算出一個方法解析順序(MRO)列表,這個MRO列表就是一個簡單的全部基類的線性順序列表
爲了實現繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類爲止
而這個MRO列表的構造是經過一個C3線性化算法來實現的. 咱們不去深究這個算法的數學原理, 它實際上就是合併全部的MRO列表並遵循以下三條準則:
1.子類會先於父類被檢查
2.多個父類會根據它們在列表中的順序被檢查
3.若是對下一個類存在兩個合法的選擇,選擇第一個父類
1 繼承順序 2 3 4 class A: 5 def test(self): 6 print("testA") 7 class B(A): 8 def test(self): 9 print("testB") 10 class C(A): 11 def test(self): 12 print("testC") 13 class D(B): 14 def test(self): 15 print("testD") 16 class E(C): 17 def test(self): 18 print("testE") 19 class F(D,E): 20 def test(self): 21 print("testF") 22 f1 = F() 23 print(F.__mro__)#(<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) 24 f1.test()#實例調用方法時,遵循mro順序,會優先從子級尋找,找不到往上,先廣度優先,若還找不到會找最深一級,若尚未會報錯
1 class jiaotong: 2 def __init__(self,name,speed): 3 self.name = name 4 self.speed = speed 5 def run(self): 6 print("%srunning!"%self.name) 7 class bicycle(jiaotong): 8 def __init__(self,name,speed,type): 9 #jiaotong.__init__(self,name,speed)#第一種方法:類調用,子級繼承父級,能夠在調用父級方法的基礎上進行派生,減小重複代碼 10 super().__init__(name,speed)#第二種方法:用內置super().調用父級方法 11 self.type = type 12 def run(self): 13 jiaotong.run(self) 14 print("%s開動了"%self.name) 15 16 17 f1 = bicycle("danche",10,"meilida") 18 print(f1.name,f1.speed,f1.type) 19 f1.run()
多態:調用不一樣的子類將會產生不一樣的行爲,多態是在繼承上實現的
1 class Dt: 2 def __init__(self,name,temputer): 3 self.name = name 4 self.temputer = temputer 5 def fu(self): 6 if self.temputer < 0: 7 print("【%s】溫度過低變成冰了!"%self.name) 8 elif self.temputer > 0 and self.temputer < 100: 9 print("【%s】變成水了!"%self.name) 10 elif self.temputer > 100: 11 print("【%s】溫度過高變成蒸汽了!"%self.name) 12 w1 = Dt("water",-2) 13 ice = Dt("ice",5) 14 steam = Dt("steam",150) 15 w1.fu() 16 ice.fu() 17 steam.fu()
封裝的概念就是隱藏
第一層面的封裝: 類就是麻袋, 這自己就是一種封裝
第二個層面的封裝:類中定義私有的, 只在類的內部使用,外部沒法訪問, 類中定義屬性名時在其前面加上_或者__可實現該屬性的隱藏,但這種隱藏只是一種語言上的約定,python並不會從底層禁止你訪問
class People: _population = "60億" __star = "earth" def __init__(self,name,salary): self.name = name self.slary = salary p1 = People("tom",1000) print(p1._population)#對於第一種用_封裝的屬性,雖然是私有的,但仍然能夠訪問 print(p1._People__star)#對於第二種用__封裝的屬性,在其前面加上_類名仍然能夠訪問
python並不會真的阻止你訪問私有屬性, 模塊也遵循這種預約, 若是模塊名以單下劃線開頭, 那 麼from module import *時不能導入,可是你from module import _private_module依然是能夠導 入的
其實不少時候你去調用一個模塊的功能時會遇到單下劃線開頭的
(socket._socket,sys._home,sys._clear_type_cache),這些都是私有的, 原則上是供內部調用的,
但經過特殊方法依然能夠調用
注意 : 雙下劃線開頭的屬性在繼承給子類時, 子類是沒法覆蓋的(原理也是基於python自動作了
雙下劃線開頭的名字的重命名工做)