1. 程式人生 > >面向物件-反射

面向物件-反射

vars(),dir(),locals()

vars()和dir()返回的結果有區別:

dir()和vars()的區別就是:dir()只打印屬性,vars()則列印屬性與屬性的值。

a = 1
b = 2
print(vars())           #{...}  字典形式      key:value         {變數名:值}
print(dir())            #[...]  列表形式        key                 [變數名]

dir():

  預設列印當前模組的所有屬性,如果傳一個物件引數則列印當前物件的屬性
vars():

  預設列印當前模組的所有屬性,如果傳一個物件引數則列印當前物件的屬性
  函式以字典形式返回引數中每個成員的當前值,如果vars函式沒有帶引數,那麼它會返回包含當前區域性名稱空間中所有成員的當前值的一個字典。

locals() 不傳引數(也不能傳引數)的情況下,和vars() 一樣 #{...} 字典形式 key:value {變數名:值}

class A:
    name = 1
    b = 2
    def func(self):
        print(111)

dic = vars(A)
print(dic['name'])         
#1

str 
= input("請輸入:") # 類似eval print(dic['%s'%str]) #print(vars('%s'%str)) 用字串操作變數名,函式名

-

class A:
    a = 1
    b = 2
    def __init__(self):
        self.c = 3
    def func(self):
        print(111)
a = A()
print(vars(a))              #{'c': 3}      檢視物件的屬性
複製程式碼

反射

什麼是反射:

  反射的概念是由Smith在1982年首次提出的,主要是指程式可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。

python面向物件中的反射:

  通過字串的形式操作物件相關的屬性。python中的一切事物都是物件(都可以使用反射)

四個可以實現自省的函式: 下列方法適用於類和物件(一切皆物件,類本身也是一個物件)

hasattr(obj,屬性)         #檢測物件是否擁有這個屬性
getattr(obj,屬性)         #檢視物件 的屬性
setattr(obj,屬性,值)      # 新增/修改 屬性
delattr(obj,屬性)         # 刪除屬性

示例:

class Foo:
    def __init__(self,name):
        self.name = name
    def func(self):
        return 123

f = Foo('kitty')


print(hasattr(f,'name'))      #檢測物件是否擁有這個屬性
print(hasattr(f,'age'))
#True
#False


print(getattr(f,'name'))        #檢視物件 的屬性
#kitty
a = getattr(f,'func')       # 函式的記憶體地址
print(a())                      # 函式的記憶體地址()    呼叫函式
# 123
print(getattr(f,'age','如果不存在,返回我'))    #不設定第三個引數,會報錯:'Foo' object has no attribute 'age'
# 如果不存在,返回我             # 可以設定返回值


setattr(f,'age',18)             # 新增新屬性
print(f.age)
# 18
setattr(f,'age',66)             # 修改屬性
print(f.age)
# 66
setattr(f,'age_2',lambda self,n: n**2)
print(f.age_2(f,4))
# 16


delattr(f,'age')
print(f.age)        ##AttributeError: 'Foo' object has no attribute 'age'
print(getattr(f,'age','如果不存在,返回我'))
#如果不存在,返回我

擴充套件:程式碼級別能解決的(能用if 解決的)問題, 就不用try except

還是上面的類和物件
import logging

if hasattr(f,'job'):            #  如果輸入錯誤,就報錯
    print(getattr(f,'job'))
else:logging.warning("不存在job屬性")
#WARNING:root:不存在job屬性

注意:
  getattr()拿到的只是一個名字
  拿到方法名之後,如果要呼叫方法,需要加括號“()”

總結:

反射就是 使用字串資料型別的變數名 獲取屬性值或呼叫方法 

 

小結:
  hasattr(類名,'屬性名') 返回True或False
  屬性值 = getattr(類名,'屬性名')
  方法的記憶體地址 = getattr(類名,'方法名')
  方法的記憶體地址()

#### 物件的空間沒有 類的方法 在類裡面

 

物件的反射

類的反射 (python一切皆物件,類也是物件)

模組的反射 (python一切皆物件,模組也是物件)

本模組的反射

a = 2
import sys
obj = sys.modules['__main__']       #只有本模組可以用'__main__',但是,假如a模組引用b模組,就不行了(參考if __name__ = '__main__':)
print(getattr(obj,'a'))
# 2

-

a = 2
import sys
obj = sys.modules[__name__]         #萬能寫法  不管匯入到任何模組,__name__都等於那個模組的名字
print(getattr(obj,'a'))
# 2

# 反射就是:通過 字串 去操作物件(例項化物件 類, 模組)。
# 對例項化物件的示例