python3 面向對象編程


一.面向對象編程 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>
類對象的創建方式2

 

四.屬性

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
限制對象屬性的添加__slots__

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
 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
只讀屬性2

 

五.方法

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>>
init()

(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
str和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
__call__

(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
getitem
 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
iter

(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}
property
 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
super
 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
super

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
抽象

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM