PYTHON開發必備技能(5)

來源:互聯網
上載者:User

標籤:簡單的   show   經典的   eth   對象   直接   ESS   pytho   common   

Python反射機制

我記得以前學習Java的時候,就接觸到了反射的概念,後來隨著工作,經常聽到反射的概念,今天決定好好總結一下。

下面3篇部落格我感覺寫的很不錯,大家可以進行參考。

71406953

http://www.mamicode.com/info-detail-1401422.html

https://www.cnblogs.com/huxi/archive/2011/01/02/1924317.html

首先大家需要知道反射的概念,比較經典的解釋分為以下幾種:

  • 通過字串的形式來尋找或操作對象內部的屬性叫做反射
  • 通過字串映射或者修改程式運行時的狀態、屬性或者方法叫做反射
  • 反射是通過字串的形式操作對象相關的成員,反射的的本質其實就是利用字串的形式去對象(模組)中操作(尋找/擷取/刪除/添加)成員,一種基於字串的事件驅動!

在python當中一切事物皆對象,所以都可以使用反射

python中的反射功能涉及到四個內建函數:hasattr、getattr、setattr、delattr,這四個函數分別用於對對象內部執行:檢查是否含

有某個成員、擷取成員、設定成員、刪除成員。

樣本程式1:訪問成員的兩種方式:obj.與obj.__dict__[‘成員‘]

#!/usr/bin/python# -*- coding:utf-8 -*-class Student(object):    def __init__(self,name,age):        self.name = name        self.age = age    def study(self,name):        print(‘%s is studing‘%self.name)student = Student(‘angela‘,25)print(student.__dict__)  #查看student的成員屬性(名稱空間對應的成員)print(vars(student))     #查看student的成員屬性(名稱空間對應的成員)#通過字串直接存取對象所對應的成員.print(student.__dict__[‘name‘],student.__dict__[‘age‘])print(student.__dict__.get(‘name‘))print(student.__dict__.get(‘age‘))#當然,我們一般都是這樣子的,但是上面的那種方式是根本print(student.name,student.age)

運行結果:

{‘name‘: ‘angela‘, ‘age‘: 25}{‘name‘: ‘angela‘, ‘age‘: 25}angela 25angela25angela 25Process finished with exit code 0

 

Python當中的反射涉及到了四個主要方法

hasattr(obj,name_str):判斷對象obj是否含有名為name_str的方法或者靜態屬性,傳回值為布爾值,即通過字串的形式來判斷對

象內部是否含有某個屬性。

getattr(obj,name_str):根據字串name_str去擷取對象obj當中對應函數的記憶體位址或者靜態屬性對應的數值,如果傳回值為函數

的記憶體位址,需要加上括弧才能夠調用。

setattr(obj,name_str,value): 添加或者修改obj對象當中名為name_str的屬性或者方法的數值。

delattr(obj,name_str): 刪除obj對象當中名為name_str的屬性。

 

 

樣本程式:Python當中的反射對應的四個方法

#!/usr/bin/python# -*- coding:utf-8 -*-class Student(object):    def __init__(self,name,age):        self.name = name        self.age = age    def study(self,name):        print(‘%s is studing‘%self.name)student = Student(‘angela‘,25)print(student.__dict__)  #查看student的成員屬性(名稱空間對應的成員)#檢查對象是否含有某個成員.print(hasattr(student,‘name‘))print(hasattr(student,‘study‘))#通過字串擷取對象當中某個成員對應的數值.func = getattr(student,‘study‘)print(func)func(student)#通過字串設定或增加對象當中某個成員的數值setattr(student,‘name‘,‘Jack‘)setattr(student,‘salary‘,2000)print(student.__dict__)#通過字串刪除對象當中的某個成員.delattr(student,‘name‘)delattr(student,‘salary‘)print(student.__dict__)#設定成員的時候還可以增加方法成員.setattr(student,‘show‘,lambda num:num+1)print(vars(student))

運行結果:

{‘name‘: ‘angela‘, ‘age‘: 25}TrueTrue<bound method Student.study of <__main__.Student object at 0x000000000219D400>>angela is studing{‘salary‘: 2000, ‘name‘: ‘Jack‘, ‘age‘: 25}{‘age‘: 25}{‘show‘: <function <lambda> at 0x0000000001E5CBF8>, ‘age‘: 25}Process finished with exit code 0

  

 樣本程式:在Python當中,萬物皆對象,所以只要是對象,就可以使用反射。

accout.py包含的內容:

#!/usr/bin/python# -*- coding:utf-8 -*-import sys#在Python當中,一切皆對象:只要是對象,就可以使用反射機制.class Person(object):    def __init__(self,name,age):        self.name = name        self.age = age    def eat(self,name):        print(‘%s is eating‘%self.name)if __name__ == ‘__main__‘:    #擷取當前的模組對象,並擷取該模組對象對應的數值.    module_name = sys.modules[__name__]    print(module_name.__dict__)

visit.py執行的內容:

#!/usr/bin/python# -*- coding:utf-8 -*-import accountif hasattr(account,‘Person‘):    student = getattr(account,‘Person‘)(‘angela‘,25)    print(student.__dict__)    if hasattr(student,‘eat‘):        func = getattr(student,‘eat‘)        func(student)

運行結果:

{‘age‘: 25, ‘name‘: ‘angela‘}angela is eatingProcess finished with exit code 0

  

反射的應用情境:

在程式當中,如果我們想通過一個字串變數var來匯入一個模組或者一個模組下的某個方法,這個時候直接執行import var是會報錯

的,因為var在程式當中是一個變數,通過字串變數來直接調用名字看起來相同的函數是不可行的,這個時候就需要使用到反射。

根據使用者輸入的url的不同,調用不同的函數,實現不同的操作,也就是一個web url路由器的功能,這在web架構裡是核心組件之一。

 

樣本程式1:首先,有一個commons模組,它裡面有幾個函數,分別用於展示不同的頁面,代碼如下:

#!/usr/bin/python# -*- coding:utf-8 -*-def login():    print(‘這是一個登陸頁面!‘)def logout():    print(‘這是一個退出頁面!‘)def home():    print(‘這是網站的首頁面.‘)

隨後,有一個visit模組,通過這個模組可以登入到不同的頁面(簡易版程式),如果沒有使用到反射,大部分人可能會這樣寫:

#!/usr/bin/python# -*- coding:utf-8 -*-import commonsdef run():    inp = input(‘請輸入你想訪問的頁面的url:‘).strip()    if inp == ‘login‘:        commons.login()    elif inp == ‘logout‘:        commons.logout()    elif inp == ‘home‘:        commons.home()    else:        print(‘404‘)if __name__ == ‘__main__‘:    run()

運行結果樣本:

請輸入你想訪問的頁面的url:login這是一個登陸頁面!Process finished with exit code 0  

 如果你會使用反射的話,我們就可以這樣寫(萬物皆對象)

import commonsdef run():    inp = input(‘請輸入你想訪問的頁面的url:‘).strip()    if hasattr(commons,inp):        func = getattr(commons,inp)        func()    else:        print(‘404‘)if __name__ == ‘__main__‘:    run()

  

 樣本程式2:我們在類比一個Ftp的例子,其實道理都是一樣的,在Python當中,萬物皆對象,只要是對象,就可以使用反射

#!/usr/bin/python# -*- coding:utf-8 -*-class Ftp_Client(object):    def __init__(self,host):        self.host = host        print(‘正在串連機器:‘,host,‘....‘)    def run(self):        while True:            line = input(‘請輸入你需要操作的命令:‘).strip()            cmd = line.split()[0]            file_name = line.split()[1]            if hasattr(self,cmd):                func = getattr(self,cmd)                print(func)                func(file_name)            else:                print(‘您輸入的指令不存在.‘)    def get(self,filename):        print(‘正在下載檔案%s,稍等...‘%filename)ftp_client = Ftp_Client(‘127.0.0.1‘)ftp_client.run()

運行結果:

正在串連機器: 127.0.0.1 ....請輸入你需要操作的命令:get word.txt<bound method Ftp_Client.get of <__main__.Ftp_Client object at 0x00000000024F9A20>>正在下載檔案word.txt,稍等...請輸入你需要操作的命令:put word.txt您輸入的指令不存在.請輸入你需要操作的命令:

  

樣本程式3:反射機制還經常用到協同開發過程當中。

假設現在有一個人A:正在開發一個介面,授權介面:grant。

#!/usr/bin/python# -*- coding:utf-8 -*-class Ugdap(object):    def __init__(self,db_name,table_name):        self.db_name = db_name        self.table_name = table_name    # def grant(self):    #     """    #     :return: 該介面正在開發中...    #     """    #     print(‘進行中授權.‘)

作為調用介面的我,不確認介面是否已經開發完畢,於是我可以這麼寫:

#!/usr/bin/python# -*- coding:utf-8 -*-from commons import UgdapUgdap_obj = Ugdap(‘fdm‘,‘exe_cool_data_operate‘)if hasattr(Ugdap_obj,‘grant‘):    func = getattr(Ugdap_obj,‘grant‘)    print(func)    func()else:    print(‘無法擷取到介面資訊,跳過該步驟.‘)

  

 反射的意義:

可能有人會問python不是有兩個內建函數exec和eval嗎?他們同樣能夠執行字串。比如:

12345 exec("print(‘haha‘)") 結果: haha

那麼直接使用它們不行嗎?非要那麼費勁地使用getattr,__import__幹嘛?

其實,在上面的例子中,圍繞的核心主題是如何利用字串驅動不同的事件,比如匯入模組、調用函數等等,這些都是python的反射機

制,是一種編程方法、設計模式的體現,凝聚了高內聚、松耦合的編程思想,不能簡單的用執行字串來代替。當然,exec和eval也有它

的舞台,在web架構裡也經常被使用。

 

PYTHON開發必備技能(5)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.