反射机制是通过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接收三个参数:对象,对象的属性或方法,以及未获取到时的默认返回值。

  1. class MyClass(object):
  2. country = "China"
  3. def __init__(self, name, age):
  4. self.name = name
  5. self.age = age
  6. self._gender = None
  7. def hello(self):
  8. print("I'm {}, {}.".format(self.name, self.age))
  9. def gender(self, gender):
  10. self._gender = gender
  11. print(self._gender)
  12.  
  13. print(getattr(MyClass, "country")) # 获取对象的静态属性
  14. my = MyClass("Li", 24)
  15. print(getattr(my, "name")) # 获取实例的变量(属性)
  16. getattr(my, "hello")() # 获取并执行实例的方法
  17. getattr(my, "gender")("female") # 传入参数

二、通过反射获取模块的方法

  1.访问当前模块的对象

  1. def func():
  2. func.name = "Li"
  3. func.age = 24
  4. print("I'm {}, {}.".format(func.name, func.age))
  5.  
  6. if __name__ == '__main__':
  7. import sys
  8. # 需要引入sys模块,用sys.modelus["__main__"]访问当前模块的内存地址
  9. getattr(sys.modules["__main__"], "func")() # 从模块中获取属性
  10. print(getattr(func, "name"))

  2.访问其它模块的对象

  将上面的代码保存到test1.py文件中,在test2.py中导入test1.py,同样可以访问MyClass类。

  1. import test1
  2. if __name__ == '__main__':
  3. MyClass = getattr(test1, "MyClass") # 这里也可以用sys.modules["test1"]来替代test1
  4. print(MyClass.country)
  5. my = MyClass("Li", 24)
  6. print(getattr(my, "name")) # 获取实例的变量(属性)
  7. getattr(my, "hello")() # 获取并执行实例的方法
  8. getattr(my, "gender")("female") # 传入参数

三、__import__和importlib.import_module

  python3提供了一个特殊的方法:__import__(字符串参数)。__import__()方法会根据参数,动态的导入同名的模块。它的功能和getattr相似。

  将test2.py中的代码改为下面两行,即可实现同样的功能。

  1. module = __import__("test1")
  2. fun = getattr(module, "func")()

  或者这样写:

  1. import importlib
  2. module = importlib.import_module("test1")
  3. fun = getattr(module, "func")()

  它们都是根据模块名来访问该模块的内存空间,从而获取全局变量、函数或者类等对象。

  来看一段文档介绍:

  1.   Docstring:
  2.   __import__(name, globals=None, locals=None, fromlist=(), level=0) -> module
  3.  
  4.   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''.
  5.   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来设置,其它不起作用
  1. module = __import__("test1", ) # 它相当于import test1
  2. # module = __import__("test.person", fromlist=True) # 它相当于from test import person
  3. # 从模块中导入py文件,test是一个package,包含__init__.py和person.py
  4. # person.py中包含MyClass类
  5. Myclass = getattr(module, "MyClass")
  6. my = Myclass("Li", 24)
  7. my.hello()

  importlib的用法也相似。

  1. import importlib
  2. # module = importlib.import_module("test1") # import test1
  3. # module = importlib.import_module("test.person", package=True) # from test import person
  4. module = importlib.import_module("test_outer.test.person", package=True) # from test_outer.test import person
  5. Myclass = getattr(module, "MyClass")
  6. my = Myclass("Li", 24)
  7. my.hello()

四、例子

  1.遍历模块查找所需函数

  1. # 文件夹
  2. test
  3. - __init__.py
  4. - drink.py # 定义一个drink函数,打印"I'm drinking."
  5. - person.py
  6. - say.py # 同drink.py
  7. - sleep.py # 同drink.py

  person.py

  1. import os
  2. import importlib
  3.  
  4. class Person:
  5. def __init__(self, name):
  6. self.name = name
  7. self.modules = self.py_list()
  8.  
  9. def py_list(self):
  10. pys = os.listdir(os.path.dirname(__file__))
  11. modules = []
  12. for py in pys:
  13. if py.endswith(".py") and not py.startswith("__"):
  14. modules.append(importlib.import_module(py.split(".")[0])) # 将多个模块全部导入到一个list中
  15. return modules
  16.  
  17. def action(self):
  18. while True:
  19. imp = input("小明 >>> ")
  20. fun = None
  21. for module in self.modules: # 遍历查询module,查找imp函数
  22. if hasattr(module, imp):
  23. fun = getattr(module, imp)
  24. break
  25. if fun:
  26. fun()
  27. else:
  28. print("Order isn't correct.")
  29.  
  30. if __name__ == '__main__':
  31. per = Person("Li")
  32. per.action()

  2.动态导入模块

  当然,也可以根据模块名和对象名,来获取相应的模块,并调用相应的方法。从而不必将所有的模块都导入进来。

  1. import importlib
  2. class Person:
  3. def __init__(self, name):
  4. self.name = name
  5.  
  6. def action(self):
  7. while True:
  8. imp = input("小明 >>> ")
  9. try:
  10. module, fun = imp.split("/")
  11. module = importlib.import_module(module,)
  12. if hasattr(module, fun):
  13. getattr(module, fun)()
  14. else:
  15. print("Order isn't correct.")
  16. except:
  17. print("input not correct.")
  18.  
  19. if __name__ == '__main__':
  20. per = Person("Li")
  21. per.action() # 需要输入sleep/sleep 或者drink/drink

  3.setattr的使用

  1. import importlib
  2. class Person:
  3. def __init__(self, name):
  4. self.name = name
  5. def sleep(self):
  6. getattr(importlib.import_module("sleep"), "sleep")()
  7. def drink(self):
  8. getattr(importlib.import_module("drink"), "drink")()
  9. def fun(self, action):
  10. if hasattr(self, action):
  11. getattr(self, action)
  12. else:
  13. setattr(self, action, self.error) # 设置aciton的函数,当然可以在上面的getattr的default关键字中设置
  14. getattr(self, action)() # 调用action的函数
  15. def error(self):
  16. print("error.")
  17.  
  18. if __name__ == '__main__':
  19. per = Person("Li")
  20. per.fun("wth")

python(八):反射的更多相关文章

  1. python的反射机制

    转载自:http://www.cnblogs.com/feixuelove1009/p/5576206.html 对编程语言比较熟悉的朋友,应该知道"反射"这个机制.Python作 ...

  2. python的反射

    目前大多数网站都是通过路由的方法来,处理url请求,如果有很多个url的话,不停的include或者用if判断匹配,似乎不太符合情理,因此这里讲讲python的反射机制, 自动装在模块.请看下面的实例 ...

  3. 简单谈谈python的反射机制

    转:http://www.jb51.net/article/87479.htm 本文主要介绍python中的反射,以及该机制的简单应用,熟悉JAVA的程序员,一定经常和Class.forName打交道 ...

  4. python八荣八耻

    Python八荣八耻 以动手实践为荣 , 以只看不练为耻; 以打印日志为荣 , 以单步跟踪为耻; 以空格缩进为荣 , 以制表缩进为耻; 以单元测试为荣 , 以人工测试为耻; 以模块复用为荣 , 以复制 ...

  5. 【转】简单谈谈python的反射机制

    [转]简单谈谈python的反射机制 对编程语言比较熟悉的朋友,应该知道“反射”这个机制.Python作为一门动态语言,当然不会缺少这一重要功能.然而,在网络上却很少见到有详细或者深刻的剖析论文.下面 ...

  6. Python(八) 正则表达式与JSON

    一.初识正则表达式 正则表达式 是一个特殊的字符序列,一个字符串是否与我们所设定的这样的字符序列,相匹配 快速检索文本.实现替换文本的操作 json(xml) 轻量级 web 数据交换格式 impor ...

  7. Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究

    Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究 一丶反射 什么是反射: ​ 反射的概念是由Smith在1982年首次提出的 ...

  8. 三十八、python中反射介绍

    一.反射:根据字符串的形式去对象(某个模块)中去操作成员通过字符串的形式,导入模块通过字符串的形式,去模块中寻找指定的函数,并执行 1.__import__:用于字符串的形似执行导入模块 inp=in ...

  9. Python之反射,正则

    本节主要内容: 一. 反射: getattr hasattr setattr defattr 二. 补充模块中特殊的变量 三. 正则表达式 re模块 (一)反射: hasattr(object, na ...

随机推荐

  1. codeforces600E Lomsat gelral

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  2. Elasticsearch 使用技巧笔记

    1.重新分片 当出现Unassigned分片时,我们可以通过分片重分配解决这个问题 curl -X PUT http://192.168.0.37:9200/_cluster/settings \ - ...

  3. ubuntu install vue , vue-cli , how to create project..

    <<install node.js <<the n model is manage the node.js version npm install -g n n stable ...

  4. Angular2 中的依赖包详解

    转自:http://blog.csdn.net/feiying008/article/details/53033704 目录 dependencies 和 devDependencies depend ...

  5. SqlLocalDB命令

    SqlLocalDB info    (查询所有LocalDB实例) SqlLocalDB start 实例名称    (查看某个LocalDB实例状态信息) SqlLocalDB create 实例 ...

  6. model 数据注解

    https://www.cnblogs.com/leoxuan/articles/6555396.html ASP.NET MVC5中Model层开发,使用的数据注解有三个作用: 数据映射(把Mode ...

  7. tcp/ip学习笔记-TCP

    tcp/ip学习笔记-TCP 彭会锋 报文发送采用的是tcp_output函数,

  8. 进程上下文频繁切换导致load average过高

    一.问题现象 现网有两台虚拟机主机95%的cpu处于idle状态,内存使用率也不是特别高,而主机的load average达到了40多. 二.问题分析 先在主机上通过top.free.ps.iosta ...

  9. PyCharm在win10的64位系统安装实例

    搭建环境 1.win10_X64,其他Win版本也可以. 2.PyCharm版本:Professional-2016.2.3. 搭建准备 1.到PyCharm官网下载PyCharm安装包. 2.选择W ...

  10. Highcharts 基本曲线图;Highcharts 带有数据标签曲线图表;Highcharts 异步加载数据曲线图表

    Highcharts 基本曲线图 实例 文件名:highcharts_line_basic.htm <html> <head> <meta charset="U ...