所谓的反射,实质上就是“根据字符串形式的内容,去对象中操作成员“。

  一、用字符串调用模块

  通常调用模块时,使用:import *** 或者from *** import *** 的形式。这里的***是在软件中直接指定好的模块名称。如果根据用户输入的字符串调用模块,需要使用:__import__('***')。

module_name = input('需要调用的模块是:') # 输入shutil后
DD = __import__(module_name)
DD.rmtree('codes')  # 目录被删除
View Code

  如:DD = __import__('os') 等价于 import os as DD

  二、用字符串去模块中寻找函数并执行

  python有四个内置函数与此相关:getattr()、hasattr()、setattr()、delattr()。  

  (一)getattr(object,name,default=None)调用模块内部函数或变量

# 调用模块内部函数和变量

# 1、调取MD模块中的函数f1,不执行
# ret = getattr(MD,'f1')  # 返回函数
# print(type(ret))  # <class 'function'>

# 2、调取MD模块中的函数f1,并执行
# ret = getattr(MD,'f1')()  # f1()无返回值
# print(type(ret))  # <class 'NoneType'>

# # 3、调取MD模块中的函数f2,并执行
# ret = getattr(MD,'f2')()    # f2()有返回值
# print(ret,type(ret))  # f2 <class 'str'>

# # 4、调取MD模块中的变量
# ret = getattr(MD,'age')
# print(ret,type(ret))   #  10 <class 'int'>
#
# ret = getattr(MD,'name')
# print(ret,type(ret))   #  lucy <class 'str'>
#
# ret = getattr(MD,'__file__')
# print(ret,type(ret))   #  D:\pycharm\dongxuew\lib.py <class 'str'>
#
# ret = getattr(MD,'__name__')
# print(ret)             # lib

# # 5、调取内容不再模块内,直接报错
# getattr(MD,'f5')
# # AttributeError: module 'lib' has no attribute 'f5'

# 6、调取内容不再模块内,返回,不报错
getattr(MD,'f5',None)
View Code

  注意:name使用时需要字符串形式,可以是函数名也可以是变量名。getattr()调取函数时,若要直接执行,后面需要加括号()。调取内容不存在时,默认报错,通过设置参数default可以取消报错。

  (二)hasattr(object,name)判断模块中是否含有被调用的内容

ret = hasattr(MD,'__name__')
print(ret)  # True

ret = hasattr(MD,'name')
print(ret)  # True

ret = hasattr(MD,'f4')
print(ret)  # False

ret = hasattr(MD,'f2')
print(ret)  # True
View Code

  注意:内容存在时,返回True;内容不存在时,返回False。

  (三)setattr(object,name,func)在内存中为模块添加变量或简单函数

print(hasattr(MD,'num'))  #  False
setattr(MD,'num',12)
print(hasattr(MD,'num'))  #  True

setattr(MD,'f4',print('f4'))
getattr(MD,'f4')          #  f4
View Code

  (四)delattr(object,name)在内存中删除模块的变量或者函数

# 删除在内存中新增变量
setattr(MD,'num',12)
print(hasattr(MD,'num'))  #  True
delattr(MD,'num')
print(hasattr(MD,'num'))  #  False
# 删除模块中函数
print(hasattr(MD,'f1')) # True
delattr(MD,'f1')
print(hasattr(MD,'f1')) # False
View Code

  注意:setattr 和 delattr 都是在内存中操作的,与模块文件无关。