一句话:以字符串形式导入模块,以字符串形式执行函数。
__import__(model):以字符串形式导入模块
getattr(model. func):以字符串形式执行函数
使用反射:可以避免耦合(大型程序比如工厂模式)
开胃小菜:
来活了,你老板给你一个excle表,里面是这样的:
hostname | memory |
主机A | 8*8 |
主机B | 16*8 |
你从表中读出的数据是a = '8*8',string类型,老板想让你对里面的内容计算,怎么弄呢?
eval函数用来执行一个字符串的表达式,然后返回表达式的值。
a = '8*8'
eval(a)
>>> 64
反射来了~~~
需求:给了你字符串,通过字符串导入模块(不能直接用import sys)
temp = 'sys' # sys是一个模块,平时就是import os 就可以了,但是我想让你通过字符串的形式导入
# 也就是说给了你一个变量temp,不准用import sys,就把sys模块导入进来
-----------------------------------------------------------------------------------------
temp = 'sys'
model = __import__(temp)
print model.path # path是sys模块里面的方法,用于显示路径
>>>['C:\\Users\\Mr.xiao\\PycharmProjects\\18day03\\main',
'C:\\Users\\Mr.xiao\\PycharmProjects\\18day03']等等
继续反射~~~
需求:
两个数据库模块,sql和sqlserver,两个模块内都有两个计算同样用户某样数据个数的函数count(),一个含有1条,一个含有2条,
之前都是使用
import sqlserverhelper
print sqlserverhelper.count()
现在该数据库down机了,要改数据库,需要下面形式进行改
import mysqlhelper
print mysqlhelper.count()
但是太麻烦了,还只是在mian函数里面改的
闪亮登场-----------反射(可以读string类型,通过字符串的形式导入模块,并且以字符串的形式执行函数)
------------以字符串的形式导入模块------------
# temp = 'mysqlhelper' ---修改方便
temp = 'sqlserverhelper'
model = __import__(temp)
print model.count >>>
------------以字符串的形式执行函数------------
temp = 'mysqlhelper' 模块(字符串形式)(我自己写的模块?)
func = 'count' 模块里面的函数(字符串形式)
model = __import__(temp)
Function = getattr(model, func) # getattr就是去model这个模块中获取model中的函数,并且这个函数名是以字符串形式的
print Function >>>function count at 0x0000000002E5C518>
1.getattr() 获取模块中的某一个函数
2.hasattr() 判断某一个函数中有没有某一个函数
module = __import__('sqlserverhelper')
print dir(module) >>>['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'count']
val = hasattr(module, 'version')
print val
>>>False
3.delattr() 删除模块中的某一个函数
------------------------------
反射用武之地~~~
需求:我们根据用户输入的url的不同,去返回给用户不同的界面(url 规范 xxx/xxx)
1. ************搬砖式:************
from backend import account
data = raw_input('请输入地址:')
# array = data.split('/')
if data == 'account/login':
account.login()
elif data == 'account/logout':
account.logout()
要是有1W个地址你写1W行????
反射上!
2. **************反射:*************所有的主流web框架在干的事
data = raw_input('请输入地址')
array = data.split('/')
userspance = __import__(array[0]) # 导入模块account,array得到的是xxx/xxx中的前一个xxx
func = getattr(userspance, array[1]) # 注意,这个func的返回值就相当于整个函数
func() # 执行函数
# 详细解析,getattr的第一个参数是我们导入的模块,第二个参数是模块的函数,都是str类型的
但是上述代码执行不了 >>> ImportError: No module named account
注意 我们自己导入模块的时候:
上面代码在执行 userspance = __import__(array[0]) 的时候,是不是忘了点东西?上面的userspance是通过account.array[0],并没有加backend
所以我们这里的userspance = __import__(array[0])就相当于这一句
import backend.account(这里的backend是需要加一个字符串的拼接):__import__('backend.'+array[0])
所以说我们想要调用里面的函数的话还得再导入一次模块,因为上面是account.login(),还需要account这个模块嘛
func = getattr(userspance, array[1])
func()
data = raw_input('请输入地址:')
array = data.split('/')
userspance = __import__('backend.'+array[0])
model = getattr(userspance, array[0])
func = getattr(model,array[1])
func()
总结: