一.面向對象編程 OOP (Object Oriented Programming)
1.OOP是一種計算機編程架構,計算機程序是由單個能夠起到子程序作用的單元或對象組合而成,即把對象作為程序的基本單元。
2.面向對象本身是對面向過程的封裝。
3.OOP的三大特點:封裝、繼承和多態。
4.python是一門徹底的面向對象編程(opp)的語言,python中萬物皆對象。
5.python中,所有數據類型都可以視為對象,當然也可以自定義對象。自定義的對象數據類型就是面向對象中的類(Class)的概念。
6.python中,一個對象包括:屬性和方法(變量+函數)
二.類(Class)和實例(Instance)
1.對象:類和實例
(1)類:用來描述具有相同的屬性和方法的對象的集合,類本質上也是對象
(2)實例:具有屬性和方法的對象,實例本質上也是對象,在python中實例也被稱為對象,為了區別於整個的對象概念,把它稱作實例
(3)實例抽象出類,類實例化為實例,一個類可以有多個實例
(4)類和實例相當於抽象和具體的關系:比如:類:學生;實例:張三
2.python中默認繼承(object)的類,也被稱作新式類
3.python中通過一個類對象來創建另一個類對象或對應的實例對象,
4.創建類對象的類被稱作元類,type是終極元類
5.類和對象:(1)類=對象=類對象;類屬性(2) 對象=對象=一般對象=實例;對象屬性=實例屬性
三.創建類和實例
1.通過class 創建一個類
2.類的創建流程:檢測__metaclass__屬性:該類--父類--模塊中--type元類
3.根據類名實例化一個實例
4.類名(money)是變量(money),變量(類名)引用該類,類實例化對象,由變量(one)引用該對象,由該對象里面的__class__找到該類

1 class Money: 2 pass
3 one=Money() 4 print(type(Money)) 5 print(type(one)) 6 print(Money.__name__)#訪問類的名稱
7 print(one.__class__)#訪問實例對應的類
8 ----------------------------------------------------------------------
9 <class 'type'>
10 <class '__main__.Money'>
11 Money 12 <class '__main__.Money'>

1 #type(cls, what, bases=None, dict=None):
2 # 創建類:類名=type(類,父類(),{__dict__})
3 #通過元類創建
4 a=10
5 print(type(a)) 6 xxx=type('dog',(),{'count':0}) 7 print(xxx) 8 print(xxx.__dict__) 9 d=xxx() 10 print(d) 11 -------------------------------------------
12 <class 'int'>
13 <class '__main__.dog'>
14 {'count': 0, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'dog' objects>, '__weakref__': <attribute '__weakref__' of 'dog' objects>, '__doc__': None} 15 <__main__.dog object at 0x0307C4B0>
四.屬性
1.類屬性和實例屬性
(1)類屬性:定義在類中且在函數體之外,可以通過類名訪問其屬性;類屬性被對應的各個實例中共享;類屬性通常不作為實例屬性使用
(2)實例屬性:定義在方法中的屬性,只作用於當前實例的類
(3)類對象的__dict__屬性(只讀屬性)默認不能被賦值修改,可以通過setattr方法修改;而一般對象里面的__dict__屬性能被直接修改
(4)一般情況下,屬性存儲在__dict__的字典中,有些內置對象沒有這個__dict__屬性
(5)能通過實例找到類屬性,不能通過類訪問實例屬性
(6)變量后面加_:表示與系統關鍵字進行區分的命名方式;變量后面加__:表示系統內置的寫法
(7)實例屬性訪問機制:getattribute方法---調用描述器方法的get方法---實例自身的dict字典---對應類的dict字典---父類(上層)的dict字典---調用getattr方法
2.類屬性的增、刪、改、查

1 class money: 2 age=19
3 num=123 #直接在類中添加屬性
4 money.count=1#給類增加一些屬性,類屬性=值
5 money.age=3#給類的屬性直接賦值;來改變屬性值
6 print(money.count) 7 print(money.age) 8 print(money.__dict__)#查看類的所有屬性,以字典形式返回(類的內置屬性和創建的屬性)
9
10 m=money 11 print(m.age)#通過對象訪問類的屬性
12 print(m.__name__) 13 print(m.__class__) 14
15 #del 刪除類的直系屬性
16 #不能通過對象刪除累屬性
17 -----------------------------------------------------
18 1
19 3
20 {'__module__': '__main__', 'age': 3, 'num': 123, '__dict__': <attribute '__dict__' of 'money' objects>, '__weakref__': <attribute '__weakref__' of 'money' objects>, '__doc__': None, 'count': 1} 21 3
22 money 23 <class 'type'>
24
25 類屬性
3.實例屬性的增、刪、改、查

1 class Person: 2 pass
3 p=Person() 4
5 #給p對象增加一些屬性,對象屬性=值
6 p.age=18
7 #驗證是否有添加成功
8 print(p.age) 9 print(p.__dict__)#查看對象的所有屬性,以字典形式返回
10
11 p.age=[1,3]#修改操作,直接賦值修改對象的屬性,id會變
12 print(p.age) 13
14 p.age.append('小花')#訪問操作,操作(添加)值,id不變
15 print(p.age) 16
17 #del 刪除
18 ---------------------------------------------------------
19 18
20 {'age': 18} 21 [1, 3] 22 [1, 3, '小花']
4.限制實例屬性的添加__slots__

1 class person: 2 __slots__ = ['age']#限制對象屬性的添加
3 pass
4 p1=person() 5 p1.age=10
6 # p1.num=10 報錯AttributeError: 'person' object has no attribute 'num'
7 print(p1.age) 8 ----------------------------------------------
9 10
5.python中對象的屬性查找機制:優先到對象自身去查找屬性,找到則結束;如果沒找到,則根據__class__找到對象對應的類,到類里面查找
6.公有屬性、受保護屬性、私有屬性
(1)公有屬性:共享的屬性,一般的屬性
(2)受保護屬性:受到保護的屬性,用 _ 前綴表示
(3)私有屬性:防止外界直接訪問,防止被子類同名稱屬性覆蓋,進行數據保護和數據過濾,用 __ 前綴表示,實例不能訪問私有屬性

1 class person: 2 def __init__(self): 3 self.__age=18
4
5 def setAge(self,value): 6 if isinstance(value,int) and 0<value<200:#數據過濾
7 self.__age=value 8 else: 9 print('數據錯誤') 10
11 def getAge(self): 12 return self.__age
13
14 p=person() 15 print(p._person__age) 16 p.setAge(20) 17 print(p._person__age) 18 print(p.getAge()) 19 -------------------------------------------------
20 18
21 20
22 20
私有屬性的訪問(名字重整):__類名 變為 _類名__x

1 class Animal: 2 __x = 10
3 def test(self): 4 print(Animal.__x) 5 print(self.__x) 6
7 print(Animal.__dict__) 8 print(Animal._Animal__x) 9 -------------------------------------------------
10 {'__module__': '__main__', '_Animal__x': 10, 'test': <function Animal.test at 0x0304C618>, '__dict__': <attribute '__dict__' of 'Animal' objects>, '__weakref__': <attribute '__weakref__' of 'Animal' objects>, '__doc__': None} 11 10
7.只讀屬性(只能讀取,不能寫入):(1)先私有化,再部分公開,;利用@property裝飾器(2)__setattr__

1 class Person: 2 def __init__(self): 3 self.__age=18
4
5 def getAge(self): 6 return self.__age
7
8 @property # 可以將一些屬性的操作方法關聯這個方法
9 # property(fget=Nofne, set=None, fdel=None, doc=None)
10 def age(self): 11 return self.__age
12 p=Person() 13 print(p.getAge()) 14 print(p.age) 15 # p.age=666 #AttributeError: can't set attribute
16 -------------------------------------------------------------
17 18
18 18

1 class Person: 2 def __setattr__(self, key, value): 3 print(key, value) 4 if key=='age'and key in self.__dict__.keys(): 5 print('只讀屬性') 6 else: 7 self.__dict__[key]=value 8
9 p=Person() 10 p.age=19
11 p.name='sz'
12 print(p.__dict__) 13 print(p.age) 14 p.age=12
15 print(p.age) 16 -------------------------------------------
17 age 19
18 name sz 19 {'age': 19, 'name': 'sz'} 20 19
21 age 12
22 只讀屬性 23 19
五.方法
1.在類內部,使用 def 關鍵字來定義一個方法;調用:對象.方法
2.與一般函數定義不同,方法必須包含形式參數 self, 且為第一個參數,self 代表的是對象本身
3.self 代表的是類的實例,代表當前對象的地址,而 self.class 則指向類,self 不是 python 關鍵字,可以認為方法中的self其實就是實例對象的唯一標志
4.實例方法、類方法、靜態方法
(1)無論哪種類型的方法,都是存儲在類中,在類的__dict__指向的字典中,沒有在實例當中的方法

1 class person: 2 def shilifangfa(self): 3 print('實例方法',self) 4
5 @classmethod 6 def leifangfa(cls): 7 print('類方法',cls) 8
9 @staticmethod 10 def jingtaifanggfa(): 11 print('靜態方法') 12
13 p=person() 14 p.shilifangfa() 15 print(p) 16 # person.shilifangfa()#TypeError: shilifangfa() missing 1 required positional argument: 'self'
17
18 person.leifangfa() 19 person.jingtaifanggfa() 20 -----------------------------------------------------------------
21 實例方法 <__main__.person object at 0x052B6070>
22 <__main__.person object at 0x052B6070>
23 類方法 <class '__main__.person'>
24 靜態方法
(2)實例方法:默認第一個參數需要接受到一個實例;調用:對象.方法
(3)類方法:默認第一個參數需要接受到一個類,綁定在類上的方法

1 class Person: 2 @classmethod#類方法裝飾器
3 def leifangfa(cls,a):#第一個參數默認為類
4 print('類方法',cls,a) 5
6 Person.leifangfa(123)#通過類來調用
7 p=Person() 8 p.leifangfa(666)#通過實例來調用
9
10 func=Person.leifangfa#通過定義函數的形式來調用
11 func(111) 12
13 class A(Person): 14 pass
15 A.leifangfa(1)#通過衍生類來調用
16 ----------------------------------------------------------
17 類方法 <class '__main__.Person'> 123
18 類方法 <class '__main__.Person'> 666
19 類方法 <class '__main__.Person'> 111
20 類方法 <class '__main__.A'> 1
21
22 類方法
(4)靜態方法:第一個參數什么也不默認接受;

1 class Person: 2 @staticmethod#靜態方法裝飾器
3 def jingtai(): 4 print('靜態方法') 5
6 Person.jingtai()#通過類來調用
7 p=Person() 8 p.jingtai()#通過實例來調用
9 func=Person.jingtai#通過定義函數的形式來調用
10 func() 11 ------------------------------------------
12 靜態方法 13 靜態方法 14 靜態方法
(5)三種方法的訪問權限

1 class Person: 2 age=5
3 def shilifangfa(self): 4 print('實例方法',self) 5 print(self.age) 6 print(self.num) 7
8 @classmethod 9 def leifangfa(cls): 10 print('類方法',cls) 11 print(cls.age) 12 print(cls.num) 13 @staticmethod 14 def jingtaifanggfa(): 15 print('靜態方法') 16 print(Person.age)#訪問類屬性
17
18 p=Person() 19 p.num=10
20 p.shilifangfa()#實例方法既能訪問實例屬性,又能訪問類屬性
21
22 # p.leifangfa()#AttributeError: type object 'Person' has no attribute 'num'
23 #Person.leifangfa()#AttributeError: type object 'Person' has no attribute 'num'
24 #類方法不能訪問實例屬性,但能訪問類屬性
25
26 Person.jingtaifanggfa() 27 #靜態方法可以訪問類屬性,但不能訪問實例屬性
28 --------------------------------------------------------------------
29 實例方法 <__main__.Person object at 0x054B6170>
30 5
31 10
32 靜態方法 33 5
5.類的私有方法__private_method(相似私有屬性):聲明該方法為私有方法,只能在類的內部調用 ,不能在類地外部調用,self.__private_methods
6.類的特殊方法
(1)init初始化

1 class myclass: 2 """一個簡單是實例"""
3 i=21313
4 def f(self): 5 return 'hello world'
6
7 #__init__()將對象創建為有初始狀態的
8 #類定義了 __init__() 方法的話,類的實例化操作會自動調用 __init__() 方法
9 # __init__() 方法可以有參數,參數通過 __init__() 傳遞到類的實例化操作上
10 def __init__(self,realpart): 11 self.r = realpart 12
13
14 x=myclass(3.4) # 實例化類
15 print(x.r) 16 print(x.f) 17 ------------------------------------------------------------------
18 3.4
19 <bound method myclass.f of <__main__.myclass object at 0x057C73D0>>
(2)信息格式化操作,用字符串描述實例:__str__和__repr__

1 class person: 2 def __init__(self,n,a): 3 self.name=n 4 self.age=a 5 def __str__(self):#信息格式化,用字符串描述實例,面向用戶,通過print或str觸發
6 return '姓名:{},年齡:{}'.format(self.name,self.age) 7 def __repr__(self):#信息格式化,用字符串描述實例,面向開發人員,通過實例本身或repr觸發
8 return 'repr'
9 #先找__str__,如果沒有,再找__repr__
10 p=person('sz',18) 11 print(p.name) 12 print(p,type(p))#方法里的返回值#沒有__str__方法時<__main__.person object at 0x04C86070>
13 print(str(p),type(str(p)))#字符串
14 print(repr(p))#獲取實例的本質信息,可以用eval再次轉換
15 -------------------------------------------
16 sz 17 姓名:sz,年齡:18 <class '__main__.person'>
18 姓名:sz,年齡:18 <class 'str'>
19 repr
(3)調用操作:__call__方法,使對象具備當做函數來調用的能力

1 class person: 2 def __init__(self,name): 3 self.name=name 4 def __call__(self,age): 5 print('姓名:{},年齡:{}'.format(self.name,age)) 6
7
8 p=person('zyl') 9 p(28)#使實例能被調用,傳入參數
10 p(23) 11 p(14) 12 ---------------------------------------------
13 姓名:zyl,年齡:28
14 姓名:zyl,年齡:23
15 姓名:zyl,年齡:14
(4)索引操作:對一個實例進行索引,三個內置方法:setitem,getitem,delitem

1 class person: 2 def __init__(self): 3 self.cache={}#增加一個字典屬性
4 def __setitem__(self, key, value):#設置/增添鍵值
5 print('setitem',key,value) 6 self.cache[key]=value 7
8 def __getitem__(self, item):#獲取鍵值
9 # print('getitem',item)
10 return self.cache[item] 11
12 def __delitem__(self, key):#刪除操作
13 # print('setitem',key)
14 del self.cache[key] 15
16
17 p=person() 18 p['name']='sz'#setitem
19 print(p['name'])#getitem
20 del p['name'] 21 print(p.cache)#查詢字典
22 ---------------------------------------------------
23 setitem name sz 24 sz 25 {}
(5)切片操作:對一個實例進行切片操作,三個內置方法:setitem,getitem,delitem

1 class person: 2 def __init__(self): 3 self.items=[1,2,3,4,5,6,7,8,]#初始化以列表形式
4 def __setitem__(self, key, value):#切片時只能修改,不能新增
5 print(key,value) 6 print(key.start) 7 print(key.stop) 8 print(key.step) 9 self.items[key]=value 10 #if isinstance(key,slice):#容錯處理
11 # self.items[key.start:key.stop:key.step]=value
12
13 def __getitem__(self, item):#獲取信息
14 print('getitem',item) 15
16 def __delitem__(self, key):#刪除
17 print('setitem',key) 18
19
20 p=person() 21 print(p) 22 print(p.items) 23 p[0:4:2]=['a','b']#對進行切片操作,修改列表
24 print(p.items) 25 -------------------------------------------------------------------
26 <__main__.person object at 0x0352C4B0>
27 [1, 2, 3, 4, 5, 6, 7, 8] 28 slice(0, 4, 2) ['a', 'b'] 29 0 30 4
31 2
32 ['a', 2, 'b', 4, 5, 6, 7, 8]
(6)比較操作:比較大小,真假

1 class person: 2 def __init__(self,age,height): 3 self.age=age 4 self.height=height 5 def __eq__(self, other):#實現相等操作
6 print(other) 7 return self.age==other.age#返回操作后的值
8 def __ne__(self, other):#不相等
9 print('xxx') 10 def __gt__(self, other):#大於
11 pass
12 def __ge__(self, other):#大於等於
13 pass
14 def __lt__(self, other):#小於
15 print('lt') 16 def __le__(self, other):#小於等於
17 pass
18 def __bool__(self):#布爾類型,返回實例是True還是False
19 return self.age>18#返回值控制實例是True還是False
20
21
22 p1=person(18,180) 23 p2=person(17,190) 24 print(p1==p2) 25 print(p1!=p2) 26 print(p1<p2) 27 -------------------------------------------------
28 <__main__.person object at 0x059A60D0>
29 False 30 xxx 31 None 32 lt 33 None
(7)遍歷操作:getitem、iter、next,類中同時有iter和next方法的實例才是一個迭代器,利用iter獲取迭代器對象,利用next訪問迭代器

1 class person: 2 def __init__(self): 3 self.result=1
4 def __getitem__(self, item): 5 self.result+=1
6 if self.result>=6: 7 raise StopIteration('停止遍歷') 8 return self.result 9
10 p=person() 11 for i in p: 12 print(i) 13 --------------------------------------------
14 2
15 3
16 4
17 5

1 class person: 2 def __init__(self): 3 self.result=1
4 # iter優先級高於getitem
5 def __iter__(self):#獲取實例的迭代器
6 print('iter') 7 return self#返回是一個迭代器對象
8 def __next__(self):#對於迭代器調用next方法
9 self.result+=1
10 if self.result>=6: 11 raise StopIteration('停止遍歷') 12 return self.result#對於迭代器進行遍歷
13 p=person() 14 for i in p: 15 print(i) 16 --------------------------------------------
17 iter 18 2
19 3
20 4
21 5
(8)描述器:可以描述一個屬性操作的對象;property用來管理屬性訪問。資料描述器(get/set)>實例屬性>非資料描述器(get)

1 class Person(object): 2 def __init__(self): 3 self.__age=18
4 def get_age(self): 5 return self.__age
6 def set_age(self,value): 7 self.__age=value 8 #property(fget=None, fset=None, fdel=None, doc=None)
9 age=property(get_age,set_age) 10 p=Person() 11 print(p.age) 12 p.age=98
13 print(p.age) 14 print(p.__dict__) 15
16
17
18 class Person2(object): 19 def __init__(self): 20 self.__age=18
21 @property 22 def age(self): 23 return self.__age
24 @age.setter 25 def age(self,value): 26 self.__age=value 27 p2=Person2() 28 print(p2.age) 29 p2.age=98
30 print(p2.age) 31 print(p2.__dict__) 32 ----------------------------------------------------------------------
33 18
34 98
35 {'_Person__age': 98} 36 18
37 98
38 {'_Person2__age': 98}

1 class Age: 2 def __get__(self, instance, owner): 3 print('get') 4 def __set__(self, instance, value): 5 print('set') 6 def __delete__(self, instance): 7 print('delete') 8 class person: 9 age=Age()#描述器
10 def __getattribute__(self, item): 11 print('xxx') 12
13 #通過實例操作描述器
14 p=person() 15 p.age=10#調用了set,get
16 print(p.age)#調用的方法中沒有返回值
17 del p.age#調用了delete
18 #一般不通過類來操作描述器
19 print(person.age)#只是調用了get方法
20 person.age=19
21 del person.age#沒有用delete方法
22 ---------------------------------------------------------------------
23 set 24 xxx 25 None 26 delete 27 get 28 None
7.補充
(1)__new__方法:創建實例對象,將對象創建出來,返回實例對象,主要用於繼承一些不可變的類,一般默認
(2)__init__方法:初始化實例對象,一般用於定義初始化屬性,當對象被創建,自動執行,無需返回值,若還有new方法,則執行new
(3)__call__方法:使得類能像函數那樣調用,一般放類的執行
六.繼承
class DerivedClassName(BaseClassName):
<statement>
或
class DerivedClassName(modname.BaseClassName):
<statement>
其中DerivedClassName子類 BaseClassName基類

1 class people: # 類定義
2 name = '' # 定義基本屬性
3 age = 0 # 定義基本屬性
4 __weight = 0 # 定義私有屬性,私有屬性在類外部無法直接進行訪問
5
6 def __init__(self, n, a, w):# 定義構造方法
7 self.name = n 8 self.age = a 9 self.__weight = w 10
11 def speak(self): # 定義構造方法
12 print("%s 說: 我 %d 歲。" % (self.name, self.age)) 13
14 class student(people): # 單繼承示例,定義基類
15 grade = ''
16
17 def __init__(self, n, a, w, g): 18 people.__init__(self, n, a, w)# 調用父類的構函
19 self.grade = g 20
21 def speak(self): # 覆寫父類的方法
22 print("%s 說: 我 %d 歲了,我在讀 %d 年級" % (self.name, self.age, self.grade)) 23
24 class speaker(): # 另一個類,多重繼承之前的准備
25 topic = ''
26 name = ''
27
28 def __init__(self, n, t): 29 self.name = n 30 self.topic = t 31
32 def speak(self): 33 print("我叫 %s,我是一個演說家,我演講的主題是 %s" % (self.name, self.topic)) 34
35 # 多重繼承
36 class sample(speaker, student): 37 a = ''
38
39 def __init__(self, n, a, w, g, t): 40 student.__init__(self, n, a, w, g) 41 speaker.__init__(self, n, t) 42
43
44 test = sample("Tim", 25, 80, 4, "Python") 45 test.speak() # 方法名同,默認調用的是在括號中排前地父類的方法
46 ------------------------------------------------------------------------------
47 我叫 Tim,我是一個演說家,我演講的主題是 Python
1.子類(派生類)繼承父類(超類)(基類):子類擁有父類一些資源的'使用權'
2.父類---共性;子類---特性
3.單繼承:僅僅繼承一個父類;多繼承:繼承多個父類;多繼承分為無重疊的多繼承,有重疊的多繼承
4.可以在子類中重寫父類的方法
5.supper()調用父的一個方法,自動找到所有基類以及對應的方法

1 class Dongwu(): 2 def __init__(self,name): 3 self.name=name 4 def shengming(self): 5 print('dongwu') 6
7 class Gou(Dongwu): 8 def __init__(self,name,color): 9 super().__init__(name) #調用父類的一個方法,從父類獲得繼承
10 self.color=color #在子類中添加新的內容
11 def shengming(self): 12 print('gou') 13 def kanjia(self): 14 print('kanjia') 15
16 a1=Dongwu('a1') 17 a2=Gou('a2',1) 18 print(a1.shengming(),a2.shengming()) 19 ----------------------------------------------------------------------------
20 dongwu 21 gou

1 class D: 2 def __init__(self): 3 print('d') 4 class B(D): 5 def __init__(self): 6 D.__init__(self)#調用父類的方法
7 print('b') 8 class C(D): 9 def __init__(self): 10 super().__init__() 11 print('c') 12 class A(C,B): 13 def __init__(self): 14 # B.__init__(self)
15 # C.__init__(self)調用了兩次
16 #super沿着mro鏈條,找到下一級節點,去調用對應的方法
17 #super(__class__, <first argument>)沿着參數二的mro鏈條,找參數一的下一個節點
18 #使用參數二進行調用
19 super(A, self).__init__() 20 # super().__init__()
21 print('a') 22 C() 23 A() 24 -------------------------------------
25 d 26 c 27 d 28 b 29 c 30 a
6.type和object
(1)type:元類,實例化其他類,包括object類,type類實例化object類
(2)object:所有類的父類,包括type類,type類繼承object類
7.資源:除了私有的方法和屬性,其他的基本都能繼承;資源的‘使用權’實質上指資源的訪問權,並不是指資源的復制
8.資源的使用:
(1)單繼承鏈:從下到上
(2)無重疊的多繼承鏈:從左到右,從上到下
(3)有重疊的多繼承鏈:從上到下,從左到右,(新式類,c3算法)

1 #查看資源查找順序
2 import inspect 3 class animal: 4 pass
5 class person(animal): 6 pass
7 inspect.getmro(person)#查看類資源的訪問循序
8 print(person.__mro__) 9 print(person.mro()) 10 ---------------------------------------------------------------
11 (<class '__main__.person'>, <class '__main__.animal'>, <class 'object'>) 12 [<class '__main__.person'>, <class '__main__.animal'>, <class 'object'>]

1 class D: 2 pass
3 class B(D): 4 pass
5 class C(D): 6 pass
7 class A(C,B): 8 pass
9 print(A.mro()) 10 -----------------------------------------------
11 [<class '__main__.A'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.D'>, <class 'object'>]
9.資源的覆蓋:屬性的覆蓋和方法的重寫;本質是訪問優先級順序決定的
七.內存管理機制
1.所有對象都會在內存中開辟一塊空間進行存儲;根據不同的類型及內容開辟不同的空間大小進行存儲,並返回該空間的地址給外界接受(引用),用於后續對這個對象的操作
2.對於整數和短小的字符,python會進行緩存,不會創建多個相同對象
3.容器對象(列表,元組,字典,自定義類對象等),存儲的其他對象,僅僅是其他對象的引用,並不是其他對象本身
4.引用計數器:對象自身被引用的個數

1 import sys 2 class person: 3 pass
4 p1 = person() # p1引用person類對象====把person類對象的地址賦值給p1
5 print(sys.getrefcount(p1))#查看p1引用的對象的引用個數,注意初始為一即結果是:實際引用個數加一
6 p2 = p1#把p1的值賦值給p2,p1的值是person類對象的地址,p2引用person類對象,p2的值是person類對象的地址
7 print(sys.getrefcount(p1)) # 查看對象(person類對象)引用個數,注意初始為一即結果是:實際引用個數加一
8 del p2 9 print(sys.getrefcount(p1)) #查看p1引用的對象的引用個數
10
11 #引用計數加一:
12 #p1=person()對象被創建
13 p2=p1#對象被引用,3
14 print(sys.getrefcount(p1)) 15 l=[p1]#對象作為一個元素存儲在容器中,引用次數加一,4
16 print(sys.getrefcount(p1)) 17
18 # 引用次數+2
19 def log(obj): 20 print(sys.getrefcount(obj)) 21 log(p1)#對象被作為參數,傳入到一個函數中,6
22
23 #引用次數減一:
24 #del p1對象的別名被顯示銷毀
25 #p1 = 123 對象的別名被賦予新的對象
26 #一個對象離開它的作用域:一個函數執行完畢時;內部的局部變量關聯的對象,它的引用會被釋放
27 #對象所在的容器被銷毀,或從容器中刪除對象
28 ---------------------------------------------------------------------
29 2
30 3
31 2
32 3
33 4
34 6

1 #循環引用
2 import objgraph 3 class person: 4 pass
5 class dog: 6 pass
7
8 p=person() 9 d=dog() 10 print(objgraph.count('person'))#垃圾回收器,查看跟蹤的對象個數
11 print(objgraph.count('dog')) 12 p.pet=d 13 d.master=p 14 print(objgraph.count('person')) 15 print(objgraph.count('dog')) 16
17 del p 18 del d 19 print(objgraph.count('person'))#對象並沒有被釋放
20 print(objgraph.count('dog')) 21 -----------------------------------------------------------------
22 1
23 1
24 1
25 1
26 1
27 1
5.垃圾回收機制:解決循環引用問題:找到循環引用並干掉相關對象

1 #垃圾回收機制
2 #找到循環引用
3 #1.收集所有容器對象,通過一個雙向鏈表進行引用
4 #2.對於每一個‘容器對象’,通過gc_refs來記錄當前對應的引用計數
5 #3.對於每一個‘容器對象’,找到它引用的‘容器對象’,並將這個‘容器對象’的引用計數-1
6 #4.通過引用計數判斷是否是循環引用,計數器為0的為循環引用,可以被釋放
7
8
9 #垃圾回收器中,新增的對象個數-消亡的個數達到一定閾值是才會觸發垃圾檢測
10 #垃圾回收的周期順序:0代垃圾回收一定次數才會觸發0,1代回收;1代垃圾回收一定次數才會觸發0,1,2代回收
11 import gc 12 import objgraph 13 print(gc.get_threshold())#得到垃圾檢測的參數(閾值,10代,10代)
14 gc.set_threshold(800,10,10)#設置垃圾檢測的參數
15 print(gc.get_threshold()) 16
17 #垃圾回收:
18 #自動回收:開啟垃圾回收機制;達到垃圾回收的閾值
19 print(gc.isenabled())#檢測垃圾回收機制是否開啟
20 gc.disable()#關閉垃圾回收機制
21 print(gc.isenabled()) 22 gc.enable()#開啟垃圾回收機制
23 print(gc.isenabled()) 24
25 #手動回收:
26 class person: 27 def __del__(self): 28 print('person對象被釋放了') 29 class dog: 30 def __del__(self): 31 print('dog對象被釋放了') 32 p=person() 33 d=dog() 34 #兩個實例對象之間相互引用,造成循環引用
35 p.pet=d 36 d.master=p#python2中弱引用weakref.ref()
37 del p 38 del d 39 gc.collect()#手動回收垃圾,無關垃圾自動清理機制是否開啟
40 print(objgraph.count('person')) 41 print(objgraph.count('dog')) 42 --------------------------------------------------------------------
43 (700, 10, 10) 44 (800, 10, 10) 45 True 46 False 47 True 48 person對象被釋放了 49 dog對象被釋放了 50 0 51 0
八.補充
1.如果對象的屬性和方法名相同,屬性會覆蓋方法
1.封裝:把操作和屬性封裝在一個對象中
2.多態:對象行為和屬性的多態;python中並沒有真正的多態,也不需要多態
3.一個迭代器一定是一個可迭代對象,一個可迭代對象不一定是迭代器;可迭代對象:iter;迭代器:iter和next
4.重載

1 class Dw(): 2 def __init__(self,name): 3 self.name=name 4 #<__main__.Dw object at 0x02BD73D0>
5
6 def __str__(self): 7 return self.name 8 #a
9
10 def __repr__(self): 11 return 'name:' +self.name 12 #name:a
13
14 a=Dw('a') 15 print(a) 16 ------------------------------------------------
17 a
5.組合:直接在類定義中把需要的類放進去實例化

1 #組合:把類和實例化方方放到新類中,把幾個沒有關系的類放到一起
2 class Turtle: 3 def __init__(self,x): 4 self.num=x 5 class Fish: 6 def __init__(self,x): 7 self.num = x 8 class Pool: 9 def __init__(self,x,y): 10 self.turtle=Turtle(x) 11 self.fish=Fish(y) 12 def print_num(self): 13 print(self.turtle.num,self.fish.num) 14
15 pool=Pool(1,10) 16 pool.print_num() 17 ----------------------------------------------------------------------
18 1 10
6.生成項目文檔pydoc:(1):cmd--轉到查看python文件的目錄;查看文檔描述: python -m pydoc 模塊名稱
(2)啟動本地服務,瀏覽web文檔:python -m pydoc -p 端口號
(3)生成指定模塊html文檔 : python -m pydoc -w 模塊名稱
(4)-k 查看相關的模塊
(5)-h幫助文檔python -m pydoc -h 模塊
(6)-b自己開啟端口python -m pydoc -b
7.抽象類和抽象方法:抽象類:抽象出來的類,不能直接創建實例的類,創建會報錯;抽象方法:抽象出來的方法,不具備具體實現,不能直接調用,子類不實現會報錯

1 import abc 2 class animal(object,metaclass=abc.ABCMeta): 3 @abc.abstractmethod 4 def jiao(self): 5 pass
6 class dog(animal): 7 def jiao(self): 8 print('wang') 9
10 class cat(animal): 11 def jiao(self): 12 print('miao') 13
14 def test(obj): 15 obj.jiao() 16
17 d=dog() 18 d.jiao() 19 --------------------------------------
20 wang