Python开发-033_反射
1 反射的四个函数
反射,其实可以理解成python提供了四个函数,这四个函数可以使用字符串形式操作成员
class Person(object):
def __init__(self,name,wx):
self.name = name
self.wx = wx
def show(self):
message = "姓名:{},微信:{}".format(self.name,self.wx)
print(message)
user_object = Person('kinght','kinght666')
# 在对象中获取成员
## 对象.成员 获取数据
user_object.name
user_object.wx
user_object.show()
## 反射函数 getatter(对象名,'成员名')
getattr(user_object,'name')
getattr(user_object,'wx')
getattr(user_object,'show')() # getattr获取到方法名,需要加()运行
### 如果成员不存在,设置默认返回值
v1 = getattr(user_object,'admin','没有这个成员')
print(v1) # 没有这个成员
# 对象中设置成员
## 对象名.成员名 = 值 设置成员
user_object.age = 20
## 反射函数 setattr(对象名,'成员名称','值')
setattr(user_object,'sex','man')
# 对象中是否包含成员
## 反射函数 hasattr(对象,"成员名称") 返回值 True/False
v2 = hasattr(user_object,'sex')
print(v2) # True
# 删除对象中的成员
## del 对象名.方法名
del user_object.age
v3 = hasattr(user_object,'age')
print(v3)
## 反射函数 delattr(对象,"成员名称")
delattr(user_object,'sex')
v4 = hasattr(user_object,'sex')
print(v4) # False
以后如果再遇到 对象.成员 这种编写方式时,均可以基于反射来实现
# 案例 功能选择
class Account(object):
def login(self):
return '登陆界面'
def register(self):
return '注册页面'
def run():
name = input("请输入功能选项login/register:")
account_object = Account()
try:
method = getattr(account_object,name,None)()
return method
except TypeError as e:
return "此功能模块不存在"
print(run())
2 一切皆对象
在Python中有这么句话:一切皆对象
。 每个对象的内部都有自己维护的成员。由于反射支持以字符串的形式去对象中操作成员,所以基于反射也可以对类、模块中的成员进行操作
简单粗暴:只要看到 xx.oo
都可以用反射实现
2.1 对象是对象
class Person(object):
def __init__(self,name,wx):
self.name = name
self.wx = wx
def show(self):
message = "姓名{},微信:{}".format(self.name,self.wx)
user_object = Person('kinght','kinght666')
getattr(user_object,'name')
2.2 类是对象
我们可以理解类是用一个名为class的类给实例化出来的东西
class Person(object):
name = 'kinght'
v1 = getattr(Person,'name')
print(v1) # kinght
2.3 模块是对象
import re
v1 = re.match("\w+","dfjksdufjksd")
print(v1)
func = getattr(re,'match')
v2 = func("\w+","dfjksdufjksd")
print(v2)
3 import_module + 反射
注意!在大型项目中,这个非常有用!
3.1 import_module
在模块导入的时候其实是由两种方式的
'''案例1'''
# 传统方式
import random
v1 = random.randint(1,100)
print(v1)
# import_module 方式
from importlib import import_module
m = import_module('random')
v1 = m.randint(1,100)
print(v1)
'''案例2'''
# 传统方式
from requests import exceptions as m
# import_module 方式
from importlib import import_module
m = import_module("requests.exceptions")
'''案例3'''
# 传统方式
from requests.exceptions import InvalidURL as m
# import_module 方式
from importlib import import_module
m = import_module("requests.exceptions.InvalidURL") # 报错import_module只能导入到模块级别
# 修正办法
from importlib import import_module
m = import_module("requests.exceptions")
cls = m.InvalidURL # 通过模块获取类
3.2 简化代码案例
现在有一个需求,需要使用不同的路径向用户发送信息,并且,发送方式可能随时增减
|-app.py 入口文件
|-config.py 配置文件
|_handler 功能文件(发送信息的具体功能代码)
|_email.py 发送邮件
|_msg.py 发送短信
app.py
from importlib import import_module
import config
def run():
for path in config.MESSAGE_HANDLER_LIST: # 读取配置文件信息
m,c = path.rsplit(".",1) # 循环获取模块名、类名
module = import_module(m) # 获得了模块名后,直接导入
cls = getattr(module,c) # 使用反射直接获得类名
obj = cls() # 实例化对象
obj.send() # 运行方法
if __name__ == '__main__':
run()
config.py
MESSAGE_HANDLER_LIST = [
"handler.email.Email",
"handler.msg.Msg",
]
功能模块-msg.py 简写
class Msg(object):
def send(self):
print("发送短信")
功能模块-email.py 简写
class Email(object):
def send(self):
print('发送邮件')
如果我们还需要增加模块,只需要在handler仲创建一个功能,然后写在配置文件中即可,减少模块,只需要将配置对应对应元素注释掉就行,不需要修改任何的app.py中代码
Python开发-033_反射
http://localhost:8080/archives/DKPVq5PZ