python(八):反射

來源:互聯網
上載者:User

標籤:input   argument   屬性   person   cst   error   package   []   value   

  反射機制是通過python3內建的hasattr、getattr、setattr來實現的。即根據變數名的字串形式來擷取變數名的屬性或方法。

一、通過反射查看已知對象的屬性和方法

  getattr(object, name[, default]) -> value

  Get a named attribute from an object; getattr(x, ‘y‘) is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn‘t exist; without it, an exception is raised in that case.

  getattr接收三個參數:對象,對象的屬性或方法,以及未擷取到時的預設傳回值。

class MyClass(object):    country = "China"    def __init__(self, name, age):        self.name = name        self.age = age        self._gender = None    def hello(self):        print("I‘m {}, {}.".format(self.name, self.age))    def gender(self, gender):        self._gender = gender        print(self._gender)print(getattr(MyClass, "country"))  # 擷取對象的靜態屬性my = MyClass("Li", 24)print(getattr(my, "name"))          # 擷取執行個體的變數(屬性)getattr(my, "hello")()              # 擷取並執行執行個體的方法getattr(my, "gender")("female")     # 傳入參數
二、通過反射擷取模組的方法  1.訪問當前模組的對象。  
def func():    func.name = "Li"    func.age = 24    print("I‘m {}, {}.".format(func.name, func.age))if __name__ == ‘__main__‘:    import sys      # 需要引入sys模組,用sys.modelus["__main__"]訪問當前模組的記憶體位址    getattr(sys.modules["__main__"], "func")()  # 從模組中擷取屬性    print(getattr(func, "name"))
  2.訪問其它模組的對象。

  將上面的代碼儲存到test1.py檔案中,在test2.py中匯入test1.py,同樣可以訪問MyClass類。

import test1if __name__ == ‘__main__‘:    MyClass = getattr(test1, "MyClass")  # 這裡也可以用sys.modules["test1"]來替代test1    print(MyClass.country)    my = MyClass("Li", 24)    print(getattr(my, "name"))          # 擷取執行個體的變數(屬性)    getattr(my, "hello")()              # 擷取並執行執行個體的方法    getattr(my, "gender")("female")     # 傳入參數
三、__import__和importlib.import_module

  python3提供了一個特殊的方法:__import__(字串參數)。__import__()方法會根據參數,動態匯入同名的模組。它的功能和getattr相似。

  將test2.py中的代碼改為下面兩行,即可實現同樣的功能。

module = __import__("test1")fun = getattr(module, "func")()

  或者這樣寫:

import importlibmodule = importlib.import_module("test1")fun = getattr(module, "func")()

  它們都是根據模組名來訪問該模組的記憶體空間,從而擷取全域變數、函數或者類等對象。

  來看一段文檔介紹:

  Docstring:  __import__(name, globals=None, locals=None, fromlist=(), level=0) -> module  Import a module. Because this function is meant for use by the Python interpreter and not for general use, 
  it is better to use importlib.import_module() to programmatically import a module.
  # 匯入模組應該用importlib.import_module(),__import__是提供給Python解譯器使用的。
  # globals和locals、level參數可以忽略。
  The fromlist should be a list of names to emulate ``from name import ...‘‘, or an empty list to emulate ``import name‘‘.  When importing a module from a package, note that __import__(‘A.B‘, ...) returns package A when fromlist is empty, but its submodule B when fromlist is not empty.
  # fromlist是a list of names blabla。但是試了幾次,好像只能用True來設定,其它不起作用
module = __import__("test1", )  # 它相當於import test1# module = __import__("test.person", fromlist=True)  # 它相當於from test import person# 從模組中匯入py檔案,test是一個package,包含__init__.py和person.py# person.py中包含MyClass類Myclass = getattr(module, "MyClass")my = Myclass("Li", 24)my.hello()

  importlib的用法也相似。

import importlib# module = importlib.import_module("test1")  # import test1# module = importlib.import_module("test.person", package=True)  # from test import personmodule = importlib.import_module("test_outer.test.person", package=True)  # from test_outer.test import personMyclass = getattr(module, "MyClass")my = Myclass("Li", 24)my.hello()
四、例子  1.遍曆模組尋找所需函數。
# 檔案夾test    - __init__.py    - drink.py   # 定義一個drink函數,列印"I‘m drinking."    - person.py    - say.py      # 同drink.py    - sleep.py    # 同drink.py

  person.py

import osimport importlibclass Person:    def __init__(self, name):        self.name = name        self.modules = self.py_list()    def py_list(self):        pys = os.listdir(os.path.dirname(__file__))        modules = []        for py in pys:            if py.endswith(".py") and not py.startswith("__"):                modules.append(importlib.import_module(py.split(".")[0]))  # 將多個模組全部匯入到一個list中        return modules    def action(self):        while True:            imp = input("小明 >>> ")            fun = None            for module in self.modules:  # 遍曆查詢module,尋找imp函數                if hasattr(module, imp):                    fun = getattr(module, imp)                    break            if fun:                fun()            else:                 print("Order isn‘t correct.")if __name__ == ‘__main__‘:    per = Person("Li")    per.action()
  2.動態匯入模組

  當然,也可以根據模組名和對象名,來擷取相應的模組,並調用相應的方法。從而不必將所有的模組都匯入進來。

import importlibclass Person:    def __init__(self, name):        self.name = name    def action(self):        while True:            imp = input("小明 >>> ")            try:                module, fun = imp.split("/")                module = importlib.import_module(module,)                if hasattr(module, fun):                    getattr(module, fun)()                else:                    print("Order isn‘t correct.")            except:                print("input not correct.")if __name__ == ‘__main__‘:    per = Person("Li")    per.action()   # 需要輸入sleep/sleep 或者drink/drink
  3.setattr的使用
import importlibclass Person:    def __init__(self, name):        self.name = name    def sleep(self):        getattr(importlib.import_module("sleep"), "sleep")()    def drink(self):        getattr(importlib.import_module("drink"), "drink")()    def fun(self, action):        if hasattr(self, action):            getattr(self, action)        else:            setattr(self, action, self.error)  # 設定aciton的函數,當然可以在上面的getattr的default關鍵字中設定            getattr(self, action)()  # 調用action的函數    def error(self):        print("error.")if __name__ == ‘__main__‘:    per = Person("Li")    per.fun("wth")

 

python(八):反射

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.