1.反射
1.1什么是反射
python是一門動態語言,而反射機制被視為動態語言的關鍵!
反射機制指的是:在程式的運行程序中,動態的獲取程式的資訊和物件的功能!
‘動態’:指一開始不知道程式的資訊和物件的功能,只有等到運行到那的時候才會動態獲取!!!
比如:x=18
在程式運行的時候,python才會通過反射機制動態的獲取到這個值是整型,并不需要一開始定義的時候,就規定這個18位整型!
1.2為什么要用反射機制
當我們獲取一個物件時,很多場景下,我們是并不知道這個物件里面是有什么屬性和方法的,我們需要通過反射機制,動態的獲取到該物件的屬性和方法!!
案例:當我們在接收用戶輸入指令的時候,我們接收的是一個用戶輸入的字串型別的指令,我們需要通過反射機制判斷,這個字串是不是該物件的功能,如果是呼叫該功能,如果不是回傳提示資訊!
案例代碼化:
class Func:
def put(self):
print('正在執行上傳功能')
def get(self):
print('正在執行下載功能')
# 該函式是用來接收用戶的操作指令,并判斷該物件是否有該功能,有則執行,沒有則提示沒有該功能
def action(self):
action = input('請輸入操作指令:')
if hasattr(self,action):
getattr(self,action)()
else:
print('沒有該功能')
obj = Func()
obj.action()
1.3如何實作反射機制
其實就是四個內置函式的使用!
class People:
def __init__(self,name):
self.name = name
def say(self):
pass
obj = People('zhang')
# 1.可以通過dir方法獲取obj物件有哪些屬性
print(dir(obj)) # 格式是一個串列套字串的形式
# 2.通過字串反射到真正的屬性上,從而得到屬性,操作屬性
# 四個內置函式的使用
print(hasattr(obj,'name')) # hasattr()判斷obj這個物件有沒有name這個屬性,name是字串格式
print(getattr(obj,'name')) # 等同于obj.name
setattr(obj,'name','yang') # 等同于obj.name='yang'
delattr(obj,'name') # 等同于 del obj.name
print(obj.__dict__) # 結果為{}
# 上述四個方法也可以括號里放個類,判讀類是否有該函式
res = getattr(People,'say') # 等同于People.say
print(res)
2.內置方法
2.1什么是內置方法
定義在類的內部,以__開頭__結尾的方法
特點是在滿足某種情況下自動觸發該方法!!!!
2.2為毛要用內置方法
為了自定義定制我們的類or物件
2.3如何使用內置方法
2.3.1 __str__方法
class Func:
def put(self):
print('正在執行上傳功能')
def __str__(self):
return 'w1e' # 列印物件是回傳的值,必須位字串型別
obj = Func()
print(obj) # 等同于print(obj.__str__())
# 不定義__str__方法,印出來為<__main__.Func object at 0x00000149DE206FA0>
# 定義__str__方法,可以在__str__內部函式指定回傳的東西,return后面必須是字串型別
2.3.2 __del__方法
該方法是在清理物件之前觸發,會先執行該方法
class Func:
def put(self):
print('正在執行上傳功能')
def __del__(self):
print('run...')
# 在del內部更多的是進行清理該物件占用系統的資源,物件清理了需要發起系統呼叫,清理物件占據的系統資源!
obj = Func()
del obj # 清理物件了,清理完之后會直接呼叫__del__方法,然后在執行下面的代碼;如果不手動清理,在執行代碼全部運行完之后,程式也會清理,列印run
print('====')
2.4 總結
了解:這些內置方法__str__等又稱魔法方法!
# __init__:類實體化會觸發
# __str__:列印物件會觸發
# __call__:物件()觸發,類也是物件 類(),類的實體化程序呼叫元類的__call__
# __new__:在類實體化會觸發,它比__init__早(造出裸體的人,__init__穿衣服)
# __del__:del 物件,物件回收的時候觸發
# __setattr__,__getattr__:(.攔截方法),當物件.屬性--》賦值會呼叫setattr,如果是取值會呼叫getattr
# __getitem__,__setitem__:([]攔截)
# __enter__和__exit__ 背景關系管理器
3.元類
3.1什么是元類
元類就是用來實體化產生類的類
關系:元類--->實體化--->類--->實體化--->物件(obj)
3.2如何查看內置的元類
其實,我們使用class定義的各種類和內置的類都是由內置的元類type幫我們實體化產生的
我們可以使用type()函式查看內置的元類
例如:在python中int、dict內置元類都繼承自object類,int和dict又都是type元類的物件
print(type(int)) # <class 'type'>
print(type(dict)) # <class 'type'>
那么type和object又是什么關系呢?我們來type一下object和type!
print(type(type)) #<class 'type'>
print(type(object)) #<class 'type'>
其實:
1.object的元類其實是type類,object是由type類構造出來的物件
2.type是自己的物件(指標指向了自己)
3.type類又繼承了object類
3.3class機制(class如何造出類的)
calss其實底層執行了以下四個步驟,造出了類!
class Func:
def put(self):
print('正在執行上傳功能')
def __del__(self):
print('run...')
# 1.得到類名
class_name = 'Func'
# 2.得到類的基類
class_bases = (object,)
# 3.執行類體代碼拿到名稱空間!
class_dict = {}
class_body = """
def put(self):
print('正在執行上傳功能')
def __del__(self):
print('run...')
"""
# exec第一個引數是類體代碼、第二個是類體代碼中的全域變數、第三的是一個空字典容器
exec (class_body,{},class_dict)
print(class_dict)
# 4.呼叫元類,得到People類
Func = type(class_name,class_bases,class_dict)
print(Func)
# Func類就是type元類實體化產生出來的物件!!!!
3.4如何自定義元類來控制類的產生
在3.3中,我們是使用type元類控制Func類的產生,其實,我們也可以自定義元類來控制類產生
class MyMeta(type): # 只有繼承了type的類才是元類
def __init__(self,x,y,z): # 注意呼叫MyMeta這個類其實傳入了四個引數分別是self、class_name,class_bases,class_dict
print('run...')
print(x) # x對應class_name
print(y) # y對應class_bases
print(z) # z對應class_dict
class Func(metaclass=MyMeta):
def put(self):
print('正在執行上傳功能')
def __del__(self):
print('run...')
# 在自定義類的時候,metaclass默認等于type,我們可以通過指定metaclass=MyMeta來自定義元類
# 指定了metaclass=MyMeta,其實就執行了第四步呼叫元類Func = MyMeta(class_name,class_bases,class_dict)
# 呼叫MyMeta(class_name,class_bases,class_dict)發生了三件事!
# 注意!!!呼叫它就等于呼叫了type的__call__方法!!!!
# 1.先造一個空物件---Func--這里其實先呼叫了MyMeta類里的__new__()方法
# 2.呼叫MyMeta這個類的__init__方法,完成初始化物件操作
# 3.回傳初始化好的物件
"""
完成上述操作之后,我們就可以在自定義的MyMeta元類里面的init方法里面,規定一下類的產生必須滿足那些條件!
"""
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/514227.html
標籤:其他
上一篇:Idea運行支付寶網站支付demo踩坑解決及其測驗注意事項
下一篇:Java注解(1):碼農的小秘
