python基礎---面向對象高級

面向對象高級


isinstance(obj,cls)

檢查obj是否是類 cls 的對象

class Foo(object):
    pass

obj = Foo()

print(isinstance(obj, Foo)) 
輸出:
True


issubclass(sub,super)

檢查sub類是否是 super 類的派生類

class Foo(object):
    pass

class Bar(Foo):
    pass

print(issubclass(Bar, Foo))

 

b.反射

主要是指程序可以訪問、檢測和修改它本身狀態或行爲的一種能力(自省)

python面向對象中的反射:通過字符串反射到真實的屬性上

面向對象中類中屬性的兩種調用方法:

1.   類名.屬性

2.類名.__dict__[‘屬性名’] #通過字符串的形式

class Foo:
    x=1
    def __init__(self,name):
        self.name=name

    def f1(self):
        print('from f1')


print(Foo.x)   #方法1Foo.__dict__['x']      #方法2

 

實現自省的函數,通過操作字符串的方式映射到屬性(適用於類和對象,在python中一切皆對象,類本身也是一個對象)

hasattr(obj,’name’)     判斷obj中有沒有一個name字符串對應的方法或屬性

setattr(x,’y’,’v’)     設置函數,x對象名,y屬性,v

getattr(x,’y’)         取值函數,x對象名,y屬性

delattr(x,’y’)         刪除函數,x對象名,y屬性

class Ftpserver:
    def __init__(self,host,port):
        self.host=host
        self.port=port

    def run(self):
        while True:
            cmd=input('>>: ').strip()
            if not cmd:continue    # 判斷輸入是否爲空
            if hasattr(self,cmd):   # 判斷類中是否存在此方法
                func=getattr(self,cmd)   # 取出該方法的值並賦值給func
                func()           
    def get(self):
        print('get func')

    def put(self):
        print('put func')

 

反射的好處:

1.實現可插拔機制:

可以事先把主要的邏輯寫好(只定義接口),然後後期再去實現接口的功能(首先使用hasattr進行判斷是否存在此方法,存在則執行,不存在則跳過)

2.動態導入模塊(基於反射當前模塊成員)

 

c.item系列

__setitem__      設置函數

__getitem__      取值函數

__delitem__      刪除函數

class Foo:
    def __getitem__(self, item):
        print('=====>get')
        return self.__dict__[item]

    def __setitem__(self, key, value):
        print('==============>set')
        self.__dict__[key]=value
        # setattr(self,key,value)

    def __delitem__(self, key):
        print('============>del')
        self.__dict__.pop(key)


f=Foo()
f['x']=123123123123    # 通過f[]的方式對對象進行操作時會調用item方法
print(f['x'])
del f['x'] 
輸出:
==============>set
=====>get
123123123123
============>del


d.打印對象信息__str__

class People:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

    def __str__(self):                #在對象被打印時觸發執行
        return '<name:%s age:%s sex:%s>' %(self.name,self.age,self.sex)

p1=People('egon',18,'male')
p2=People('alex',38,'male')


print(p1)
print(p2)

 

e.析構方法__del__

當對象在內存中被釋放時,自動觸發執行

注:如果產生的對象僅僅只是python程序級別的(用戶級),那麼無需定義__del__,如果產生的對象的同時還會向操作系統發起系統調用,即一個對象有用戶級與內核級兩種資源,比如(打開一個文件,創建一個數據庫鏈接),則必須在清除對象的同時回收系統資源,這就用到了__del__

典型的應用場景:

創建數據庫類,用該類實例化出數據庫鏈接對象,對象本身是存放於用戶空間內存中,而鏈接則是由操作系統管理的,存放於內核空間內存中,當程序結束時,python只會回收自己的內存空間,即用戶態內存,而操作系統的資源則沒有被回收,這就需要我們定製__del__,在對象被刪除前向操作系統發起關閉數據庫鏈接的系統調用,回收資源

class Foo:
    def __init__(self,x):
        self.x=x

    def __del__(self): #在對象資源被釋放時觸發
        print('-----del------')
        print(self)

f=Foo(100000)
del f
print('=======================>') 
# 析構方法__del__與文件處理原理差不多:
 
f=open('a.txt')  #做了兩件事,在用戶空間拿到一個f變量,在操作系統內核空間打開一個文件
del f          #只回收用戶空間的f,操作系統的文件還處於打開狀態
 
#所以我們應該在del f之前保證f.close()執行,即便是沒有del,程序執行完畢也會自動del清理資源,於是文件操作的正確用法應該是
f=open('a.txt')
f.close()  # f.close就相當於析構方法__del__,在回收用戶空間的同時回收系統空間

 

7、異常處理

異常就是程序運行時發生錯誤的信號(在程序出現錯誤時,則會產生一個異常,若程序沒有處理它,則會拋出該異常,程序的運行也隨之終止)

錯誤有兩種:

a.語法錯誤(在語法檢測階段拋出,必須在程序執行前就改正)

b.邏輯錯誤

例如:

TypeError      # 類型錯誤
for i in 3:
    pass

NameError      # 名稱錯誤
aaaaa

ValueError     # 值錯誤
int('asdfsadf')

IndexError     # 索引錯誤
l=[1,2]
l[1000]

KeyError       # key錯誤
d={'a':1}
d['b']

AttributeError # 屬性錯誤
class Foo:pass 
Foo.x

 

常見異常:

AttributeError      試圖訪問一個對象沒有的樹形,比如foo.x,但是foo沒有屬性x

IOError       輸入/輸出異常;基本上是無法打開文件

ImportError      無法引入模塊或包;基本上是路徑問題或名稱錯誤

IndentationError      語法錯誤(的子類) ;代碼沒有正確對齊

IndexError   下標索引超出序列邊界,比如當x只有三個元素,卻試圖訪問x[5]

KeyError     試圖訪問字典裏不存在的鍵

KeyboardInterrupt   Ctrl+C被按下

NameError   使用一個還未被賦予對象的變量

SyntaxError Python   代碼非法,代碼不能編譯(個人認爲這是語法錯誤,寫錯了)

TypeError   傳入對象類型與要求的不符合

UnboundLocalError  試圖訪問一個還未被設置的局部變量,基本上是由於另有一個同名的全局變量,導致你以爲正在訪問它

ValueError   傳入一個調用者不期望的值,即使值的類型是正確的

 

異常處理

a. 如果錯誤發生的條件是可預知的,我們需要用if進行處理:在錯誤發生之前進行預防

AGE=10
while True:
    age=input('>>: ').strip()
    if age.isdigit(): #只有在age爲字符串形式的整數時,下列代碼纔不會出錯,該條件是可預知的
        age=int(age)
        if age == AGE:
            print('you got it')
            break

 

b. 如果錯誤發生的條件是不可預知的,則需要用到try...except:在錯誤發生之後進行處理

異常類只能用來處理指定的異常情況,如果非指定異常則無法處理

try:
    aaaa        # 拋出NameError異常
    print('==-==>1')
    l=[]
    l[3]        # 拋出IndexError異常
    print('==-==>2')
    d={}
    d['x']      # 拋出KeyError異常
    print('==-==>3') 
# 多分支異常
except NameError as e:
    print(e)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except Exception as e:       # 萬能異常,能捕捉到所有的異常
    print(e)
else:
    print('在沒有錯誤的時候執行')
finally:
    print('無論有無錯誤,都會執行')

 

c.主動拋出異常

try:
    raise TypeError('類型錯誤')
except Exception as e:
    print(e)

 

d.自定義異常

class EgonException(BaseException):
    def __init__(self,msg):
        self.msg=msg
    def __str__(self):
        return '<%s>' %self.msg

raise EgonException('egon 的異常')

 

e.斷言

assert


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章