python中的反射
在绝大多数语言中,都有反射机制的存在。从作用上来讲,反射是为了增加程序的动态描述能力。通俗一些,就是可以让用户参与代码执行的决定权。在程序编写的时候,我们会写很多类,类中又有自己的函数,对象等等。这些类和函数都是为了后续代码服务,程序员决定什么时候用到哪一个类,什么时候调用某个函数。但很多时候,我们需要根据用户的需求来决定执行哪一段代码块。用户可能是通过点击,输入数据,或者其他方式发出指令,反射则将用户的指令传递到需要执行的那一段代码块。这个过程是自动执行的,无需人工去核对用户指令是否应该执行那一段代码,而是由反射机制自动查找该执行的代码块。大多数反射都是以web来进行举例说明,而反射本身的最常见的使用场景也确实是根据web的url不同来调用不同的函数。当然这里,我们不用讨论他的具体应用,只简单说明一下他的使用意义。
python的反射机制设定较为简单,一共有四个关键函数分别是getattr、hasattr、setattr、delattr。前两个最为常用,最后一个几乎很少用到。python本身定义的反射是指在内存中对容器里的某些元素进行操作,这个容器不仅仅包括类,还包括函数,对象,这三者不同的是在查找对象的时候,除了会查找对象自身,还会去创建对象的类里面进行查找。要用实际例子来说明一下python中的反射具体作用,先看一下需求。所有的语言中,我们都可以轻易办到让用户自由输入一个数据,然后打印那个数据,这是最简单的人机交互。在代码里的实现过程是,生成一个变量,获取用户输入数据,赋值给变量。打印变量。同理我们可以在某个类中定义两个函数,然后要求用户输入数据,根据用户输入的数据来决定具体执行哪一个函数,这就是一个人工的反射机制。当需要查找的函数只有两条的时候,我们可以用if——else进行判断。但如果数据达数百条之多,那重复性使用if不仅效率低下,而且代码量也难以估量。这种情况,就需要用到反射。具体代码如下:
#新建一个方法类 命名为echo_test 类中代码如下,定义三个函数,函数内容为打印函数名
__author__ = "lixin"
def echo_test1():
print("echo_test1")
def echo_test2():
print("echo_test2")
def echo_test3():
print("echo_test3") #另一个执行类 代码如下
__author__ = "lixin" #
import echo_test 导入方法类
func_name = input("What do you want to do?,please enter:")#请求用户输入数据
func = getattr(echo_test,func_name)#调用getattr函数,参数分别是方法类的类名,用户输入的数据。生成变量接收返回参数
func()#把变量当做方法执行 #输出结果如下
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/s11/day8/echo_example/echo_func.py
What do you want to do?,please enter:echo_test1#输入数据
echo_test1#执行结果 Process finished with exit code 0
来分析一下代码,首先说代码仅做实例,极为不完善,且输入数据只能是定义的函数的名称,但我们主要是讨论getattr的作用。从代码不难看出,它接收一个类名和一个字符串做为参数,然后去给的类里查找和字符串相同的函数名,并将那个函数的全部内容返回。所以,我们的变量实际是一个函数,因此可以直接调用。这就是一个简单的完整反射。也是python中反射最主要的功能。hasatter的作用更多是为了getattr服务。就如同上面的代码中,有可能用户输入的数据,在我们的定义的函数中并没有与之匹配的函数名,那也就无法执行。如果没有错误防御机制,程序就会崩溃,因此拿到用户输入的数据,在直接去查找执行前,需要先判断一下用户想要执行的函数是否存在,这就是hasattr的作用了 代码如下:
#在上一份代码的基础上直接更改,注意是在交互类
func_name = input("What do you want to do?,please enter:")
func = hasattr(echo_test,func_name)#getattr改为hasatter
print(func)
输出结果如下:
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/s11/day8/echo_example/echo_func.py
What do you want to do?,please enter:echo_test1
True #返回结果为布尔值 Process finished with exit code 0
以上,可以看出,hasattr函数的参数跟getattr是一样的,接收一个类和一个字符串,返回一个布尔值。它的作用就是检测用户输入的内容是否有对应的函数存在。如果有,返回true,没有,则false。我们则可以根据结果预防找不到函数的错误。因此,它和getattr常常配套使用,如果判定存在,则获取,再执行,这样可以保证代码不会运行出错。setattr的作用则是创建一个对象,代码如下:
#还是在原代码基础上修改 ,交互类
print(dir(echo_test))#首先输出一下echo_test这个类的所有方法
func_name = input("What do you want to do?,please enter:")#请求用户输入数据
func = setattr(echo_test,func_name,lambda x:x+1)
#调用setattr函数,参数分别是类名,用户输入数据,一个简单函数
print(dir(echo_test))#再次打印echo_test这个类的所有方法 """输出结果如下
第一次打印类方法结果
['__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__',
'__package__', '__spec__', 'echo_test1', 'echo_test2', 'echo_test3'] What do you want to do?,please enter:lixin
第二次打印结果
['__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__',
'__package__', '__spec__', 'echo_test1', 'echo_test2', 'echo_test3', 'lixin']"""
从输出结果分析,setattr函数的作用就是新建一个对象,参数分别是新建对象所属类的类名,新建对象的对象名,对象的值,这个值可以是字符串,也可以是数字,当然也可以是一个函数,上面代码为了简便,直接用了一个匿名函数。最后一个delattr则是删除存在的函数,使用率较低,也没什么特别注意的地方。
在使用过程中,还需要提到的就是动态获得类名,如上所有代码中的类名,都是我们固定输入的,在实际运用当中,这样会使代码极为不灵活。四个反射函数的第一个参数都只接受类名,而无法接收字符串。用户直接输入的数据,格式显然是字符串,因此无法直接使用。当然,我们可以把字符串转化成类名,但无需那么麻烦。python有相应的应对措施,使用代码如下:
#原代码基础上修改,交互类
__author__ = "lixin"
func_name = input("What do you want to do?,please enter:")#获取用户输入数据
class_name,func_name = func_name.split("/")将用户输入数据分割,并分别赋值给两个变量
model = __import__(class_name)#以__import__的形式导入类名,并生成变量获取返回值
Flog = hasattr(model,func_name)#变量值可以直接当做参数传入,在这里验证一下函数是否存在
if Flog:#如果存在在调用getattr函数,如果不存在,则提示数据有误。
func = getattr(model, func_name)
func()
else:
print("输入有误") """输出结果如下:
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/s11/day8/echo_example/echo_func.py
What do you want to do?,please enter:echo_test/echo_test1#输入内容,类名和函数名以/隔开 echo_test1
Process finished with exit code 0"""
以上,就是python中反射的常用方法了,当然在最后一段代码中,我们应该验证一下类是否存在,但python中并没有针对这个的函数了,举例中也并未给出防御机制,在实际使用中,肯定是不行的,因为类不存在,代码也无法运行,所以也要给出相应的错误防御机制。除了在类中查找函数,反射自然也能用于在函数中查找对象,在对象身上查找属性,自身方法等等。这一些操作,都是立足于内存上,而不是对代码本身进行操作。
python中的反射的更多相关文章
- Python Python中的反射机制
Python中的反射机制 by:授客 QQ:1033553122 概念 借用java中的定义:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方 ...
- Python 中的反射和自省
本文主要介绍Python中的反射和自省,以及该机制的简单应用 熟悉Java的程序员,一定经常和Class.forName打交道.即使不是经常亲自调用这个方法,但是在很多框架中(spring,eclip ...
- Python 中的反射方法
一.概述 getattr # 根据字符串为参数,去对象中找与之同名的成员. hasattr # 根据字符串为参数,去判断对象中是否有与之同名的成员. setattr # 根据字符串为参数,动态的设置一 ...
- Python基础之反射
python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员.获取成员.设置成员.删除成员. ...
- python面向对象进阶 反射 单例模式 以及python实现类似java接口功能
本篇将详细介绍Python 类的成员.成员修饰符.类的特殊成员. 类的成员 类的成员可以分为三大类:字段.方法和特性. 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存 ...
- Python之路- 反射&定制自己的数据类型
一.isinstance和issubclass isinstance(obj,cls)检查是否obj是否是类 cls 的对象 issubclass(sub, super)检查sub类是否是 super ...
- Python面向对象之-反射
Python中一切皆对象,在Python中的反射:通过字符串的形式操作对象的属性 hasattr 判断是否有改属性或者方法,有返回True,没有返回false getattr 如果是属性获得该属性 ...
- Python中实现switchcase
# 第一种方式使用python中的字典# author:wanstack def first_func(): print('first_func') def second_func(): print( ...
- Python 异常处理与反射机制
Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...
随机推荐
- phpunit 测试框架安装
PHPUnit是一个轻量级的PHP测试框架.它是在PHP5下面对JUnit3系列版本的完整移植,是xUnit测试框架家族的一员(它们都基于模式先锋Kent Beck的设计).来自百度百科 一.下载wg ...
- SQL语句/函数汇总
1.CHARINDEX(短字符A,长字符B) 说明:返回A在B的位置,从1开始,若B中不存在A,则为0 例如: SELECT CHARINDEX('aaaa','abaaaacded') ----- ...
- ThinkPhp 3.2 ajax无刷新分页(未完全改完,临时凑合着用)
临时更改后的page类(很多地方没修改...因为笔者PHP没学好..)如下: <?phpnamespace Fenye\libs; /** file: page.class.php 完美分 ...
- 第七章 人工智能,7.6 DNN在搜索场景中的应用(作者:仁重)
7.6 DNN在搜索场景中的应用 1. 背景 搜索排序的特征分大量的使用了LR,GBDT,SVM等模型及其变种.我们主要在特征工程,建模的场景,目标采样等方面做了很细致的工作.但这些模型的瓶颈也非常的 ...
- Oracle交易流水号问题
需求:生成交易流水号,每次新增一条记录时都自动加1,且流水号形式为000000001形式的10位数字. 思路:利用序列可以生成自增的流水号,只需要在前面添加N个0即可,同时,由于数字的长度一定,因此可 ...
- javascript数组array
注意:1.array的length不是只读的.可以从数组的末尾移出项或者向数组中添加新项.看下面例子: var colors = ["red","yellow" ...
- MAC OS升级到10.11(OS X EICAPTION)之后CocoaPods不能正常使用的问题解决
昨晚回家之后开始升级系统到10.11,下载了一整个晚上之后终于在早上下载完毕,早上带到公司,想查一个第三方库的时候却遇到了问题: guoyufudeMacBook-Pro:~ GuoYufu$ pod ...
- CJCMS系列---说说项目中的缓存实现(1)
缓存者,临时文件交换区也.主要就是方便查找,提高查找效率(效率在于读内存速度比读硬盘快). 大多数的项目的缓存都是通过设定过期时间来做的,可是我对于这样的替换策略不以为然,而且会导致混乱. 有人说: ...
- VSTO PowerPoint 代码删除Shape后再恢复出现无法再次获取的问题
做PowerPoint的VSTO插件项目,遇到个很奇怪的问题,当代码执行删除某些Shape时,没问题,但是操作Undo也就是恢复后,无法再次获取到之前删除的对象,这种情况只在Office2007中出现 ...
- java防止表单重复提交
用session防止表单重复提交 思路:在服务器端生成一个唯一的随机标识串Token,同时在当前用户的Session域中保存这个Token.然后将Token发送到客户端的Form表单中,在Form表单 ...