概述
運作時,差別于編譯時,指的是程式被加載到記憶體中執行的時候
反射,reflection,指的是運作時擷取類型定義資訊
一個對象能夠在運作時,像照鏡子一樣,反射出其類型資訊
簡單說,在python中,能夠通過一個對象,找出其type、class、attribute或method的能力,稱為反射或者自省。
具有反射能力的函數有:type()、isinstance()、callable()、dir()、getattr()
反射相關的函數和方法
需求
有一個Point類,檢視它執行個體的屬性,并修改它。動态為執行個體增加屬性
getattr(object,name[,default])
通過name傳回object的name屬性,當name屬性不存在,将使用default傳回,如果沒有default,則抛出AttributeError
name必須是字元串類型
default是函數,因為getattr傳回的就是一個函數,是以當找不到name對應的函數後就調用default函數。
setattr(object,name,value)
object存在name屬性時,則通過value覆寫之前name屬性
object不存在name屬性時,則新增屬性
name依然時字元串類型,value可以是一個數值,也可以是一個函數
hasattr(object,name)
判斷對象是否有這個名字的屬性,name必須為字元串
反射相關的魔術方法
getattr()、setattr()、delattr()這三個魔術方法,分别測試。
getattr()
class Base:
n = 0
class Point(Base):
z = 6
def __init__(self,x,y):
self.x = x
self.y = y
def show(self):
print(self.x,self.y)
def __getattr__(self,item):
return "missing{}".format(item)
p1 = Point(4,5)
print(p1.x)
print(p1.z)
print(p1.n)
print(p1.t)
一個類的屬性會按照繼承關系找,如果找不到,就會執行getattr()方法,如果沒有這個方法,就會抛出AttributeError異常表示找不到屬性
查找屬性順序為:
instance.dict --> instance.class.dict --> 繼承的祖先類(直到object)的dict --找不到--> 調用getattr()
setattr()
class Base:
n = 0
class Point(Base):
z = 6
def __init__(self,x,y):
self.x = x
self.y = y
def show(self):
print(self.x,self.y)
def __getattr__(self,item):
return "missing{}".format(item)
def __setattr__(self, key, value):
print("setattr {}={}".format(key,value))
#self.__dict__[key] = value #正常情況下設定屬性
#return self #傳回執行個體本身
p1 = Point(4,5)
print(p1.__dict__)
print(p1.x)
print(p1.z)
print(p1.n)
print(p1.t)
p1.name = 50
p1.x = 50
print(p1.name)
print(p1.x)
p1.__dict__["x"] = 60
print(p1.__dict__)
class Base:
n = 0
class Point(Base):
Z = 5
def __init__(self,x,y):
self.x = x
self.y = y
def __delattr__(self,item):
print("Can not del{}".format(item))
p = Point(4,5)
del p.x
print(p.dict)
p.z = 15
print(p.dict)
del p.z
del p.z
print(Point.dict)
print(p.dict)
print(Point.Z)
del Point.Z
print(Point.dict)
print(Point.Z)