博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【python之路30】反射
阅读量:5236 次
发布时间:2019-06-14

本文共 4154 字,大约阅读时间需要 13 分钟。

一、反射

1、反射的基本介绍:

反射是所有程序的专有名词,在java,C#语言中都存在反射,那么什么是反射呢?

python中 的反射概括来说:是通过字符串的形式导入模块,并通过字符串的形式去模块中寻找函数并执行。

 

2、利用字符串来导入模块

根据用户输入的模块名(input)来导入模块:

#!usr/bin/env python# -*- coding:utf-8 -*-modue = input('请输入您要导入的模块名:')RE = __import__(modue)  #相当于执行:import re as RE,__import__()把字符串形式的模块名作为模块导入

如果导入的模块是多级目录的情况:

#!usr/bin/env python# -*- coding:utf-8 -*-# from day14.lib import command# import day14.lib.commandCOM = __import__('day14.lib.command',fromlist=True)re = COM.f1()print(re)  #f1

 

 3、利用字符串来执行函数

用户输入要导入的模块,和执行的函数:

func = getattr(模块名,字符串格式的函数名),将字符串格式的函数指向func

index.py中输入代码:

#!usr/bin/env python# -*- coding:utf-8 -*-module = input('请输入您要导入的模块:')MD = __import__(module)   #如果用户输入command相当于:import command as MDfunc = input('请输入您要执行的函数:')FC = getattr(MD,func)  #如果用户输入f1相当于:创建了变量FC指向MD对象的f1函数re = FC() #相当于执行f1()print(re) #打印输出F1

 5、反射相关函数:

1)getattr(模块,字符串变量名或函数名,默认值)

#!usr/bin/env python# -*- coding:utf-8 -*-import commandf = getattr(command,'f1',None) #当字符串函数不存在时不会报错返回Nonefunc = f()print(func)

2)hasattr(模块,字符串变量名或函数名)   #判断是否存在字符串函数名

#!usr/bin/env python# -*- coding:utf-8 -*-import commandbol = hasattr(command,'f1')print(bol)  #True

3)setattr(模块,字符串变量名或函数名,设置的值)

seattr在内存中设置变量:

#!usr/bin/env python# -*- coding:utf-8 -*-import commandb1 = hasattr(command,'AGE')print(b1) #False,因为不存在AGE#当import command执行时会将command.py中的所有东西加载到内存,执行下面这句,是再在#内存中增加一个变量AGE=18setattr(command,'AGE',18)  #给command设置一个变量AGE = 18print(command.AGE) #18b2 = hasattr(command,'AGE')print(b2) #True,setattr增加了一个变量AGE

 setattr在内存中设置函数:

#!usr/bin/env python# -*- coding:utf-8 -*-import commandb1 = hasattr(command,'fn')print(b1) #False,因为不存在函数fn#当import command执行时会将command.py中的所有东西加载到内存,执行下面这句,是再在#内存中增加一个函数fnsetattr(command,'fn',lambda a:a+1)  #给command设置一个函数fn(a):return a+1b2 = hasattr(command,'fn')print(b2) #True,setattr增加了一个函数fn

4)delattr(模块,字符串函数名或变量)  #删除内存中的函数名或变量

5)总结反射的定义:

以字符串的形式去某个模块中需找东西(getattr)

以字符串的形式去某个模块中判断东西是否存在(hasattr)

以字符串的形式去某个模块中设置东西(setattr)

以字符串的形式去某个模块删除东西(delattr)

总结:以字符串中的形式去对象或模块中去操作成员(getattr、haattr、setattr、delattr)

二、基于反射模拟WEB框架的路由系统

lib文件夹下面的account.py文件中的代码为:

#!usr/bin/env python# -*- coding:utf-8 -*-def login():    print('login')def outlogin():    print('outlogin')def nb():    print('特别牛逼的功能')

和lib同目录下index.py中的文件中的代码为:

#!usr/bin/env python# -*- coding:utf-8 -*-from lib import accounturl = input('请输入URL:')if url.endswith('login'):    account.login()elif url.endswith('outlogin'):    account.outlogin()elif url.endswith('nb'):    account.nb()else:    print('404找不到页面')

用下面的代码替换上面的代码后,account中无论增加多少函数,下面的代码不用改变就可以直接执行account文件中的函数了:

#!usr/bin/env python# -*- coding:utf-8 -*-from lib import accounturl = input('请输入URL:')func_name = url.split('/')[-1]  #分隔网址,得到最后一个/后的字符串if hasattr(account,func_name):    target_func = getattr(account,func_name)  #得到目标函数    target_func()else:    print('404')

可以继续优化,如果lib文件下面有很多py文件,那么导入模块也可以设置为动态的,例如:www.bai.com/account/login,可以动态的导入account

代码如下:

#!usr/bin/env python# -*- coding:utf-8 -*-url = input('请输入URL:')fun_module,func_name = url.split('/')[-2],url.split('/')[-1] #分隔网址,得到/后最后两个字符串target_module = __import__('lib.' + fun_module,fromlist=True)  #导入lib下字符串相应的模块if hasattr(target_module,func_name):    target_func = getattr(target_module,func_name)  #得到目标函数    target_func()else:    print('404')

 三、反射在对象中使用

class Foo:    def __init__(self,name):        self.name = name    def f1(self):        print("F1")foo =Foo('sun') #Truere = hasattr(Foo,'f1') #Truere1 = hasattr(foo,'f1') #Truere2 = hasattr(foo,'name') #Trueprint(re,re1,re2)#总结:hasattr在类中可以找到方法名;#在对象中可以找到变量和方法名;因为变量是存放在对象中的,而为什么能找到方法名呢,就是反射函数可以找到对象指针指向的类中找方法

 利用反射导入有类文件,并执行文件类中的方法

#!usr/bin/env python# -*- coding:utf-8 -*-class Foo:    def __init__(self,name):        self.name = name    def f1(self):        print("F1")
s文件中的代码
#!usr/bin/env python# -*- coding:utf-8 -*-ss = __import__('s')s_class = getattr(ss,'Foo')    #获得类s_class_object = s_class('sun') #创建对象,相当于zoo = ss.Foo('sun')s_class_object_name = getattr(s_class_object,'name') #获得对象中的name字段s_class_object_f1 = getattr(s_class_object,'f1') #获得对象中的f1函数s_class_object_f1() #执行获得的函数print(s_class_object_name)
反射引入s中的类及对象

 

转载于:https://www.cnblogs.com/sunshuhai/p/6502004.html

你可能感兴趣的文章
Android中点中overlay弹出带尾巴的气泡的实现
查看>>
mxnet record 打包 Array
查看>>
逐层指定学习率
查看>>
博客园增加对emoji表情的支持,让博文更加生动
查看>>
C#: Delegate and Event
查看>>
Mybatis接口中传递多个参数
查看>>
webView 显示一个简单的网页
查看>>
在Unity中使用 luajit 64位加密
查看>>
virualbox andirodx86
查看>>
Dreamweaver层使用八定律
查看>>
SSH整合 pom.xml
查看>>
Java IO流学习总结
查看>>
day22 01 初识面向对象----简单的人狗大战小游戏
查看>>
shell的while循环
查看>>
数组的几种常用方法总结
查看>>
递归函数,二分运算,正则表达式
查看>>
阅读软件工程的问题
查看>>
【Netty】UDP广播事件
查看>>
(4)Numpy+矩阵计算+和生成
查看>>
ttt
查看>>