Python动态导入模块和反射机制详解
作者:IT界的游骑兵 发布时间:2023-07-16 14:02:10
一、前言
何谓动态导入模块,就是说模块的导入可以根据我们的需求动态的去导入,不是像一般的在代码文件开头固定的导入所需的模块。
何谓反射机制,利用字符串的形式在模块或对象中操作(查找/获取/删除/添加)成员。
下面进入具体实例介绍环节。先创建一个示例文件example.py,简单写入几个加减乘除函数,如下,方便下文讲解使用。
flag = 1 # 此变量在介绍反射机制时会用到
def my_sum(a, b):
return a + b
def my_sub(a, b):
return a - b
二、动态导入模块
一般,如果我们想从其他文件引用上面的几个函数方法,都会如下使用:
import example as count
# 加法
sum = count.my_sum(2, 3)
# 减法
sub = count.my_sub(6, 2)
print("sum: {}, sub: {}".format(sum, sub))
但现在有这样的需求,我需要动态输入一个模块名,可以随时访问到导入模块中的方法或者变量,怎么做呢?看下面。
imp = input("请输入你需要导入的模块名称:")
count = __import__(imp) # 这种方式就是通过输入字符串导入你想导入的模块
# 加法
sum = count.my_sum(2, 3)
# 减法
sub = count.my_sub(6, 2)
print("sum: {}, sub: {}".format(sum, sub))
上面实现了动态输入模块名,从而使我们能够导入模块并且执行里面的函数。但是上面有一个缺点,那就是执行的函数被固定了。那么,我们能不能改进一下,动态输入函数名,并且来执行呢?看下面。
imp = input("请输入你需要导入的模块名称:")
count = __import__(imp)
func = input("请输入你需要使用的函数名:")
f = getattr(count, func, None)
# 加法
sum = f(2, 3)
print(sum)
getattr()方法的作用是:从导入的模块中找到你需要调用的函数func,然后返回一个该函数的引用,没有找到就烦会None。
这样我们就实现了,动态导入一个模块,并且动态输入函数名然后执行相应方法。
不过,上面还存在一点点小问题:那就是我们的模块有可能不是在本级目录中存放着,有可能是如下图存放方式:
那怎么办呢?看下面。
imp = input("请输入你想导入的模块名称:")
count = __import__('first_level.{}'.format(imp), fromlist=True)
fun = input("请输入你想要使用的函数名:")
f = getattr(count, fun, None)
# 加法
sum = f(2, 3)
print(sum)
三、反射机制(又叫 python自省)
我们先来介绍python的四个内置函数:
1. getattr()
这个函数是Python自省的核心函数,具体使用上面已经介绍了,她不仅可以用于在模块中查找获取相应的方法和变量,也可以在一个对象中查找和获取相应的方法和变量,这里就不距离介绍了。
2、hasattr(object, name)
判断模块(或对象object)是否包含名为name的方法或变量(hasattr是通过调用getattr(ojbect, name)是否抛出异常来实现的)
imp = input("请输入你想导入的模块名称:")
count = __import__('first_level.{}'.format(imp), fromlist=True)
print(hasattr(count, "my_sum")) # 判断模块count中是否存在my_sum方法,存在返回True
3、setattr(object, name, value)
这是相对应的getattr()。参数是一个对象,一个字符串和一个任意值。字符串name可以是对象(object)中一个现有的属性或一个新的属性,这个函数将值(value)赋给属性(name)的。使用示例,setattr(x, y, v)相当于x.y = v。
imp = input("请输入你想导入的模块名称:")
count = __import__('first_level.{}'.format(imp), fromlist=True)
setattr(count, "flag", 0) # 即使example模块中没有flag变量,此处也成立,没有的话相当于给模块中新增一个变量flag
print(count.flag) # 打印出flag的值为0
4、delattr(object, name)
与setattr()相关的一组函数。参数是由一个对象(记住!python中一切皆是对象)和一个字符串(name)组成的。name参数必须是对象属性名之一。该函数删除该对象的一个由字符串(name)指定的属性。delattr(x, y)=del x.y.
imp = input("请输入你想导入的模块名称:")
count = __import__('first_level.{}'.format(imp), fromlist=True)
delattr(count, "flag")
print(count.flag) # 此处再打印flag的值将会报错,因为上一步已经将flag属性删除了
需要注意的是getattr,hasattr,setattr,delattr函数对模块的修改都在内存中进行,并不会影响文件中真实内容。
5、基于反射机制模拟获取web框架路由的示例
需求:输入:www.xxx.com/example/my_sum,返回执行my_sum的结果。
# 动态导入模块,并执行其中函数
url = input("url: ")
target_module = url.split('/')[-2] # 分割url,取出模块名
module = __import__('first_level.' + target_module, fromlist=True)
inp = url.split("/")[-1] # 分割url,并取出url最后一个字符串
if hasattr(module, inp): # 判断在commons模块中是否存在inp这个字符串
target_func = getattr(module, inp) # 获取inp的引用
sum_ = target_func(2, 3) # 执行
print(sum_)
else:
print("404")
来源:https://blog.csdn.net/SCF_1104/article/details/88669251


猜你喜欢
- 一.打包Flask项目1.1自己写个Flask1.2 下载pyinstallerpip install pyinstaller可选参数示例说
- WordPress 页面模板是特定的模板文件,用于特定页面或页面组,这些用于单页数据的模板显示在前端。我们还可以在 WordPre
- 使用bootstrap界面美观,可预览,可拖拽上传,可配合ajax异步或同步上传,下面是效果图:前端代码:fileinput.html<
- 前言最近尝试重新封装XMLHttpRequest,在发post请求的时候,发现express通过req.body获取不到数据,req.bod
- 使用文中提供的代码做一个统计表每天的新增行数及新增存储空间的功能实现步骤如下:1. 创建表创建表,存储每天的表空间占用情况CREATE TA
- 目的是能使用Python进行rtmp推流,方便在h264帧里加入弹幕等操作。librtmp使用的是0.3.0,使用树莓派noir官方摄像头适
- 一、UDP编程1.客户端Client:发起访问的一方。2.服务器端3.server段编程(1)建立socket,socket是负责具体通信的
- 系统环境为server20121、下载mysql解压版,解压安装包到指定目录2、在以上目录中,复制一份my-default.ini文件,重命
- suspect_pages 表位于 msdb 数据库中,是在 SQL Server 2005 中引入的。用于维护有关可疑页的信息的 susp
- 本文实例为大家分享了JDBC建立数据库连接的具体代码,供大家参考,具体内容如下import java.sql.DriverManager;i
- channel首先明确一下channel的作用:用于go协程间的通信。go语言最大的特点就是支持高并发:goroutine和channel是
- 本文讲述了Python文件操作类的操作实例,详细代码如下:#!/usr/bin/env python#!/usr/bin/env pytho
- 最近学习测试mybatis,单个增删改查都没问题,最后使用mvn test的时候发现了几个问题:1.update失败,原因是数据
- yaml简介1.yaml [ˈjæməl]: Yet Another Markup Language :另一种标记语言。
- 山河远阔,烟火人间,又一年,千里婵娟~今天给大家带来的是给玉兔投喂月饼的小游戏。八月十五中秋夜晚,让我们对着月亮许愿:希望我们在意和在意我们
- 写了网址规范化后,尚奇公司的柳先生建议再深入讨论一下301转向/重定向。下面就谈谈我所了解的301转向在搜索引擎优化方面的应用。什么是301
- 前言小伙伴a,b,c围着吃火锅,当菜上齐了,请客的主人说:开吃!,于是小伙伴一起动筷子,这种场景如何实现Event(事件)Event(事件)
- 有时需要将数组转成伪数组(ArrayLike),如下 var ary = ['one','two','
- 依赖项目基础配置使用 vue-cli 生成自适应方案核心: 阿里可伸缩布局方案 lib-flexiblepx转rem:px2rem,它有we
- 一.先看一些最简单的例子例子Table Aaid adate 1 &n