在绝大多数语言中,都有反射机制的存在。从作用上来讲,反射是为了增加程序的动态描述能力。通俗一些,就是可以让用户参与代码执行的决定权。在程序编写的时候,我们会写很多类,类中又有自己的函数,对象等等。这些类和函数都是为了后续代码服务,程序员决定什么时候用到哪一个类,什么时候调用某个函数。但很多时候,我们需要根据用户的需求来决定执行哪一段代码块。用户可能是通过点击,输入数据,或者其他方式发出指令,反射则将用户的指令传递到需要执行的那一段代码块。这个过程是自动执行的,无需人工去核对用户指令是否应该执行那一段代码,而是由反射机制自动查找该执行的代码块。大多数反射都是以web来进行举例说明,而反射本身的最常见的使用场景也确实是根据web的url不同来调用不同的函数。当然这里,我们不用讨论他的具体应用,只简单说明一下他的使用意义。

python的反射机制设定较为简单,一共有四个关键函数分别是getattr、hasattr、setattr、delattr。前两个最为常用,最后一个几乎很少用到。python本身定义的反射是指在内存中对容器里的某些元素进行操作,这个容器不仅仅包括类,还包括函数,对象,这三者不同的是在查找对象的时候,除了会查找对象自身,还会去创建对象的类里面进行查找。要用实际例子来说明一下python中的反射具体作用,先看一下需求。所有的语言中,我们都可以轻易办到让用户自由输入一个数据,然后打印那个数据,这是最简单的人机交互。在代码里的实现过程是,生成一个变量,获取用户输入数据,赋值给变量。打印变量。同理我们可以在某个类中定义两个函数,然后要求用户输入数据,根据用户输入的数据来决定具体执行哪一个函数,这就是一个人工的反射机制。当需要查找的函数只有两条的时候,我们可以用if——else进行判断。但如果数据达数百条之多,那重复性使用if不仅效率低下,而且代码量也难以估量。这种情况,就需要用到反射。具体代码如下:

  1. #新建一个方法类 命名为echo_test 类中代码如下,定义三个函数,函数内容为打印函数名
  2. __author__ = "lixin"
  3. def echo_test1():
  4. print("echo_test1")
  5. def echo_test2():
  6. print("echo_test2")
  7. def echo_test3():
  8. print("echo_test3")
  9.  
  10. #另一个执行类 代码如下
  11. __author__ = "lixin" #
  12. import echo_test 导入方法类
  13. func_name = input("What do you want to do?,please enter:")#请求用户输入数据
  14. func = getattr(echo_test,func_name)#调用getattr函数,参数分别是方法类的类名,用户输入的数据。生成变量接收返回参数
  15. func()#把变量当做方法执行
  16.  
  17. #输出结果如下
  18. /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/s11/day8/echo_example/echo_func.py
  19. What do you want to do?,please enter:echo_test1#输入数据
  20. echo_test1#执行结果
  21.  
  22. Process finished with exit code 0

  

  来分析一下代码,首先说代码仅做实例,极为不完善,且输入数据只能是定义的函数的名称,但我们主要是讨论getattr的作用。从代码不难看出,它接收一个类名和一个字符串做为参数,然后去给的类里查找和字符串相同的函数名,并将那个函数的全部内容返回。所以,我们的变量实际是一个函数,因此可以直接调用。这就是一个简单的完整反射。也是python中反射最主要的功能。hasatter的作用更多是为了getattr服务。就如同上面的代码中,有可能用户输入的数据,在我们的定义的函数中并没有与之匹配的函数名,那也就无法执行。如果没有错误防御机制,程序就会崩溃,因此拿到用户输入的数据,在直接去查找执行前,需要先判断一下用户想要执行的函数是否存在,这就是hasattr的作用了  代码如下:

  1. #在上一份代码的基础上直接更改,注意是在交互类
  2. func_name = input("What do you want to do?,please enter:")
  3. func = hasattr(echo_test,func_name)#getattr改为hasatter
  4. print(func)
  5. 输出结果如下:
  6. /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/s11/day8/echo_example/echo_func.py
  7. What do you want to do?,please enter:echo_test1
  8. True #返回结果为布尔值
  9.  
  10. Process finished with exit code 0

  

以上,可以看出,hasattr函数的参数跟getattr是一样的,接收一个类和一个字符串,返回一个布尔值。它的作用就是检测用户输入的内容是否有对应的函数存在。如果有,返回true,没有,则false。我们则可以根据结果预防找不到函数的错误。因此,它和getattr常常配套使用,如果判定存在,则获取,再执行,这样可以保证代码不会运行出错。setattr的作用则是创建一个对象,代码如下:

  1. #还是在原代码基础上修改 ,交互类
  2. print(dir(echo_test))#首先输出一下echo_test这个类的所有方法
  3. func_name = input("What do you want to do?,please enter:")#请求用户输入数据
  4. func = setattr(echo_test,func_name,lambda x:x+1)
    #调用setattr函数,参数分别是类名,用户输入数据,一个简单函数
  5. print(dir(echo_test))#再次打印echo_test这个类的所有方法
  6.  
  7. """输出结果如下
  8. 第一次打印类方法结果
  9. ['__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__',
  10. '__package__', '__spec__', 'echo_test1', 'echo_test2', 'echo_test3']
  11.  
  12. What do you want to do?,please enter:lixin
  13. 第二次打印结果
  14. ['__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__',
  15. '__package__', '__spec__', 'echo_test1', 'echo_test2', 'echo_test3', 'lixin']"""

  

从输出结果分析,setattr函数的作用就是新建一个对象,参数分别是新建对象所属类的类名,新建对象的对象名,对象的值,这个值可以是字符串,也可以是数字,当然也可以是一个函数,上面代码为了简便,直接用了一个匿名函数。最后一个delattr则是删除存在的函数,使用率较低,也没什么特别注意的地方。

在使用过程中,还需要提到的就是动态获得类名,如上所有代码中的类名,都是我们固定输入的,在实际运用当中,这样会使代码极为不灵活。四个反射函数的第一个参数都只接受类名,而无法接收字符串。用户直接输入的数据,格式显然是字符串,因此无法直接使用。当然,我们可以把字符串转化成类名,但无需那么麻烦。python有相应的应对措施,使用代码如下:

  1. #原代码基础上修改,交互类
    __author__ = "lixin"
  2. func_name = input("What do you want to do?,please enter:")#获取用户输入数据
  3. class_name,func_name = func_name.split("/")将用户输入数据分割,并分别赋值给两个变量
  4. model = __import__(class_name)#以__import__的形式导入类名,并生成变量获取返回值
  5. Flog = hasattr(model,func_name)#变量值可以直接当做参数传入,在这里验证一下函数是否存在
  6. if Flog:#如果存在在调用getattr函数,如果不存在,则提示数据有误。
  7. func = getattr(model, func_name)
  8. func()
  9. else:
  10. print("输入有误")
  11.  
  12. """输出结果如下:
  13. /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/s11/day8/echo_example/echo_func.py
  14. What do you want to do?,please enter:echo_test/echo_test1#输入内容,类名和函数名以/隔开
  15.  
  16. echo_test1
  17. Process finished with exit code 0"""

以上,就是python中反射的常用方法了,当然在最后一段代码中,我们应该验证一下类是否存在,但python中并没有针对这个的函数了,举例中也并未给出防御机制,在实际使用中,肯定是不行的,因为类不存在,代码也无法运行,所以也要给出相应的错误防御机制。除了在类中查找函数,反射自然也能用于在函数中查找对象,在对象身上查找属性,自身方法等等。这一些操作,都是立足于内存上,而不是对代码本身进行操作。

  

python中的反射的更多相关文章

  1. Python Python中的反射机制

    Python中的反射机制 by:授客 QQ:1033553122 概念 借用java中的定义:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方 ...

  2. Python 中的反射和自省

    本文主要介绍Python中的反射和自省,以及该机制的简单应用 熟悉Java的程序员,一定经常和Class.forName打交道.即使不是经常亲自调用这个方法,但是在很多框架中(spring,eclip ...

  3. Python 中的反射方法

    一.概述 getattr # 根据字符串为参数,去对象中找与之同名的成员. hasattr # 根据字符串为参数,去判断对象中是否有与之同名的成员. setattr # 根据字符串为参数,动态的设置一 ...

  4. Python基础之反射

    python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员.获取成员.设置成员.删除成员. ...

  5. python面向对象进阶 反射 单例模式 以及python实现类似java接口功能

    本篇将详细介绍Python 类的成员.成员修饰符.类的特殊成员. 类的成员 类的成员可以分为三大类:字段.方法和特性. 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存 ...

  6. Python之路- 反射&定制自己的数据类型

    一.isinstance和issubclass isinstance(obj,cls)检查是否obj是否是类 cls 的对象 issubclass(sub, super)检查sub类是否是 super ...

  7. Python面向对象之-反射

    Python中一切皆对象,在Python中的反射:通过字符串的形式操作对象的属性 hasattr  判断是否有改属性或者方法,有返回True,没有返回false getattr  如果是属性获得该属性 ...

  8. Python中实现switchcase

    # 第一种方式使用python中的字典# author:wanstack def first_func(): print('first_func') def second_func(): print( ...

  9. Python 异常处理与反射机制

    Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...

随机推荐

  1. Bzoj3894 文理分科

    Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 667  Solved: 389 Description  文理分科是一件很纠结的事情!(虽然看到这个题 ...

  2. NTFS交换数据流隐写的应用

    by Chesky ##目录 ####一.NTFS交换数据流(ADS)简介 ####二.ADS应用 写入隐藏文件(文本\图像\可执行文件) ADS在Windows平台下的利用--写入后门 ADS在We ...

  3. 如何把家里的pc改装成linux服务器

    家里有一台pc笔记本闲置在家,最近想搭建一个ubuntu系统玩一下kvm. 这个方法能避免家里宽带每隔一段时间ip自动变换. 我用到了: 1.亚马逊的aws(ec2) 2.家里的路由器 3.aws里装 ...

  4. HTTP 基础知识

    HTTP是一种协议.HTTP使用流程,一般情况下, 第一:由HTTP客户端发出请求,创建端口. 第二:HTTP服务器在端口监听客户端的请求. 第三:一旦收到请求,HTTP服务器向客户端返回状态和内容. ...

  5. MongoDB【第三篇】MongoDB基本操作

    MongoDB的基本操作包括文档的创建.删除.和更新 文档插入 1.插入 #查看当前都有哪些数据库 > show dbs; local 0.000GB tim 0.000GB #使用 tim数据 ...

  6. 转载 什么是P问题、NP问题和NPC问题

    原文地址http://www.matrix67.com/blog/archives/105 这或许是众多OIer最大的误区之一.    你会经常看到网上出现“这怎么做,这不是NP问题吗”.“这个只有搜 ...

  7. #ThinkPHP_3.2.2模型# where查询条件汇总

    特别喜欢 ThinkPHP_3.2.3 框架的Model,结合官方手册及查看源代码,汇总出其大体用法: 核心转换方法: $this->parseWhere($where); $whereStr ...

  8. 关于es5的一些新方法

    1.数组方法(1)isArray在之前我们判断数组类型的数据都是用instanceof来判断的,es5新增了对数组的判断,即Array.isArray()(2)every和some这两个方法一般用于对 ...

  9. python小知识积累

  10. 响应式web设计总结

    简单来说响应式是针对不同的屏幕的大小,比如电脑电脑.Pad设备上,屏幕比较宽的,就可以一行放多个Div.到了手机上,或者Pad竖着拿的的时候,一行就只放1到2个Div就差不多了.这样在移动设备上,无论 ...