python(八):反射
反射机制是通过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接收三个参数:对象,对象的属性或方法,以及未获取到时的默认返回值。
class MyClass(object):
country = "China"
def __init__(self, name, age):
self.name = name
self.age = age
self._gender = None
def hello(self):
print("I'm {}, {}.".format(self.name, self.age))
def gender(self, gender):
self._gender = gender
print(self._gender) print(getattr(MyClass, "country")) # 获取对象的静态属性
my = MyClass("Li", 24)
print(getattr(my, "name")) # 获取实例的变量(属性)
getattr(my, "hello")() # 获取并执行实例的方法
getattr(my, "gender")("female") # 传入参数
二、通过反射获取模块的方法
1.访问当前模块的对象
def func():
func.name = "Li"
func.age = 24
print("I'm {}, {}.".format(func.name, func.age)) if __name__ == '__main__':
import sys
# 需要引入sys模块,用sys.modelus["__main__"]访问当前模块的内存地址
getattr(sys.modules["__main__"], "func")() # 从模块中获取属性
print(getattr(func, "name"))
2.访问其它模块的对象
将上面的代码保存到test1.py文件中,在test2.py中导入test1.py,同样可以访问MyClass类。
import test1
if __name__ == '__main__':
MyClass = getattr(test1, "MyClass") # 这里也可以用sys.modules["test1"]来替代test1
print(MyClass.country)
my = MyClass("Li", 24)
print(getattr(my, "name")) # 获取实例的变量(属性)
getattr(my, "hello")() # 获取并执行实例的方法
getattr(my, "gender")("female") # 传入参数
三、__import__和importlib.import_module
python3提供了一个特殊的方法:__import__(字符串参数)。__import__()方法会根据参数,动态的导入同名的模块。它的功能和getattr相似。
将test2.py中的代码改为下面两行,即可实现同样的功能。
module = __import__("test1")
fun = getattr(module, "func")()
或者这样写:
import importlib
module = importlib.import_module("test1")
fun = getattr(module, "func")()
它们都是根据模块名来访问该模块的内存空间,从而获取全局变量、函数或者类等对象。
来看一段文档介绍:
Docstring:
__import__(name, globals=None, locals=None, fromlist=(), level=0) -> module 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''.
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来设置,其它不起作用
module = __import__("test1", ) # 它相当于import test1
# module = __import__("test.person", fromlist=True) # 它相当于from test import person
# 从模块中导入py文件,test是一个package,包含__init__.py和person.py
# person.py中包含MyClass类
Myclass = getattr(module, "MyClass")
my = Myclass("Li", 24)
my.hello()
importlib的用法也相似。
import importlib
# module = importlib.import_module("test1") # import test1
# module = importlib.import_module("test.person", package=True) # from test import person
module = importlib.import_module("test_outer.test.person", package=True) # from test_outer.test import person
Myclass = getattr(module, "MyClass")
my = Myclass("Li", 24)
my.hello()
四、例子
1.遍历模块查找所需函数
# 文件夹
test
- __init__.py
- drink.py # 定义一个drink函数,打印"I'm drinking."
- person.py
- say.py # 同drink.py
- sleep.py # 同drink.py
person.py
import os
import importlib class Person:
def __init__(self, name):
self.name = name
self.modules = self.py_list() def py_list(self):
pys = os.listdir(os.path.dirname(__file__))
modules = []
for py in pys:
if py.endswith(".py") and not py.startswith("__"):
modules.append(importlib.import_module(py.split(".")[0])) # 将多个模块全部导入到一个list中
return modules def action(self):
while True:
imp = input("小明 >>> ")
fun = None
for module in self.modules: # 遍历查询module,查找imp函数
if hasattr(module, imp):
fun = getattr(module, imp)
break
if fun:
fun()
else:
print("Order isn't correct.") if __name__ == '__main__':
per = Person("Li")
per.action()
2.动态导入模块
当然,也可以根据模块名和对象名,来获取相应的模块,并调用相应的方法。从而不必将所有的模块都导入进来。
import importlib
class Person:
def __init__(self, name):
self.name = name def action(self):
while True:
imp = input("小明 >>> ")
try:
module, fun = imp.split("/")
module = importlib.import_module(module,)
if hasattr(module, fun):
getattr(module, fun)()
else:
print("Order isn't correct.")
except:
print("input not correct.") if __name__ == '__main__':
per = Person("Li")
per.action() # 需要输入sleep/sleep 或者drink/drink
3.setattr的使用
import importlib
class Person:
def __init__(self, name):
self.name = name
def sleep(self):
getattr(importlib.import_module("sleep"), "sleep")()
def drink(self):
getattr(importlib.import_module("drink"), "drink")()
def fun(self, action):
if hasattr(self, action):
getattr(self, action)
else:
setattr(self, action, self.error) # 设置aciton的函数,当然可以在上面的getattr的default关键字中设置
getattr(self, action)() # 调用action的函数
def error(self):
print("error.") if __name__ == '__main__':
per = Person("Li")
per.fun("wth")
python(八):反射的更多相关文章
- python的反射机制
转载自:http://www.cnblogs.com/feixuelove1009/p/5576206.html 对编程语言比较熟悉的朋友,应该知道"反射"这个机制.Python作 ...
- python的反射
目前大多数网站都是通过路由的方法来,处理url请求,如果有很多个url的话,不停的include或者用if判断匹配,似乎不太符合情理,因此这里讲讲python的反射机制, 自动装在模块.请看下面的实例 ...
- 简单谈谈python的反射机制
转:http://www.jb51.net/article/87479.htm 本文主要介绍python中的反射,以及该机制的简单应用,熟悉JAVA的程序员,一定经常和Class.forName打交道 ...
- python八荣八耻
Python八荣八耻 以动手实践为荣 , 以只看不练为耻; 以打印日志为荣 , 以单步跟踪为耻; 以空格缩进为荣 , 以制表缩进为耻; 以单元测试为荣 , 以人工测试为耻; 以模块复用为荣 , 以复制 ...
- 【转】简单谈谈python的反射机制
[转]简单谈谈python的反射机制 对编程语言比较熟悉的朋友,应该知道“反射”这个机制.Python作为一门动态语言,当然不会缺少这一重要功能.然而,在网络上却很少见到有详细或者深刻的剖析论文.下面 ...
- Python(八) 正则表达式与JSON
一.初识正则表达式 正则表达式 是一个特殊的字符序列,一个字符串是否与我们所设定的这样的字符序列,相匹配 快速检索文本.实现替换文本的操作 json(xml) 轻量级 web 数据交换格式 impor ...
- Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究
Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究 一丶反射 什么是反射: 反射的概念是由Smith在1982年首次提出的 ...
- 三十八、python中反射介绍
一.反射:根据字符串的形式去对象(某个模块)中去操作成员通过字符串的形式,导入模块通过字符串的形式,去模块中寻找指定的函数,并执行 1.__import__:用于字符串的形似执行导入模块 inp=in ...
- Python之反射,正则
本节主要内容: 一. 反射: getattr hasattr setattr defattr 二. 补充模块中特殊的变量 三. 正则表达式 re模块 (一)反射: hasattr(object, na ...
随机推荐
- RK61 Keyboard Use
~ 打法: FN+shift+Esc / ? Alt Files Ctral <=> 上 下 左 右 打法:FN+shift 切换 解锁键盘 打法:FN+win 蓝牙连接 打法:FN+ ...
- 学习webpack3.x过程中遇到的问题:webpack-dev-server
这篇博客主要记录的是本人在学习webpack3.x的过程中遇到的问题(虽然这几天4.0刚出来,但是我还是先学一下3.x吧) 1.配置文件可以用webpack启服务和热更新,步骤如下: ① 先下载:we ...
- Java的 final 关键字
本文主要探讨Java final 关键字修饰变量时的用法. !!!!文末有彩蛋!!!! 1.修饰类 当用final修饰一个类时,表明这个类不能被继承.也就是说,如果一个类你永远不会让他被继承,就可以用 ...
- 【转】c++析构函数(Destructor)
创建对象时系统会自动调用构造函数进行初始化工作,同样,销毁对象时系统也会自动调用一个函数来进行清理工作,例如释放分配的内存.关闭打开的文件等,这个函数就是析构函数. 析构函数(Destructor)也 ...
- day31 堡垒机尾声 + Python与金融量化分析(一)
堡垒机尾声: 代码案例:https://github.com/liyongsan/git_class/tree/master/day31 课堂笔记:file send: 1.选择本地文件 2.远程路径 ...
- Centos7下部署两套python版本并存
Centos7下部署两套python版本并存 需求说明:centos7.2系统的开发机器上已经自带了python2.7版本,但是开发的项目中用的是python3.5版本,为了保证Centos系统的 ...
- 编写3ds max插件时遇到的问题总结
本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/ 这几天在给公司的美术编写3ds max 2009使用的插件,遇到了一些问题,在此记录一下解 ...
- 使用群晖NAS:配置Git server
1.首先在群晖的DSM的控制面板中创建一个用户例如是Git_test(我给了管理员权限) 2.在套件中心安装 Git server 3.打开Git server 勾选用户 Git_test 4.在控制 ...
- C#学习历程(六)[ref 关键字的使用]
ref 关键字的使用 ref 关键字通过引用(而非值)传递参数. 通过引用传递的效果是,对所调用方法中的参数进行的任何更改都反映在调用方法中. 例如,如果调用方传递本地变量表达式或数组元素访问表达式, ...
- ViewBag、ViewData、TempData之间的区别
1.ViewBag and ViewData(非跨视图访问) 1)ViewBag是一种dynamic动态类型,用户可以自定义属性并为其赋值,它会在运行时动态解析(例:可以作为变量.数组等各种对象传递并 ...