博客
关于我
python 反射机制
阅读量:802 次
发布时间:2023-03-07

本文共 2846 字,大约阅读时间需要 9 分钟。

一、前言

在前面的代码中,我们区分了f1和“f1”两个概念。前者是函数f1的名字,后者是一个字符串。我们不能直接用"f1"调用函数,但可以通过f1()的方式调用。这种区别提醒我们,字符串和函数名虽然看起来相似,但本质上是不同的东西。

二、web实例

在Web开发中,特别是在框架中,路由功能至关重要。它的核心作用是根据不同的URL调用不同的函数,这通常需要动态地访问模块中的函数。例如,在一个commons模块中,我们可以有多个函数,分别处理不同的页面,如login、logout和home。

以下是一个简化的示例:

  • commons模块中的函数:

    def login():    print("这是一个登录页面!")def logout():    print("这是一个退出页面!")def home():    print("这是网站主页面!")
  • visit模块作为程序入口:

    import commonsdef run():    inp = input("请输入您想访问页面的url: ").strip()    if inp == "login":        commons.login()    elif inp == "logout":        commons.logout()    elif inp == "home":        commons.home()    else:        print("404")

当我们运行visit.py并输入"home"时,会正确显示主页面。这证明了基于字符串反射的路由功能是可行的。

然而,手动写成百上千个elif显然不可行。这种情况下,我们需要一个更灵活的解决方案。

三、反射机制

为了解决动态调用函数的问题,Python提供了getattr函数。它允许我们通过字符串形式动态地访问模块中的成员。

修改后的visit模块代码如下:

import commonsdef run():    inp = input("请输入您想访问页面的url: ").strip()    func = getattr(commons, inp)    func()

getattr的使用方法是:它接收两个参数,第一个是要操作的对象,第二个是要操作的属性名(必须是字符串)。例如,getattr(commons, "login")会返回commons模块中的一个函数,如果这个函数存在的话。

这样一来,我们可以根据用户输入的URL动态地调用相应的函数,无需手动写死每一个条件判断。这种方法非常灵活,适用于有成百上千个函数的情况。

需要注意的是,getattr的第二个参数必须是一个字符串。另外,如果用户输入的URL对应的函数不存在,getattr会抛出一个AttributeError,我们需要用hasattr函数来进行检查。

四、进一步完善

为了防止非法URL导致的错误,我们可以使用hasattr函数进行检查:

import commonsdef run():    inp = input("请输入您想访问页面的url: ").strip()    if hasattr(commons, inp):        func = getattr(commons, inp)        func()    else:        print("404")

这样一来,非法的URL输入会被自动判断为404页面,避免了错误的发生。

总结一下,getattrhasattr这两个内置函数为我们提供了强大的反射能力,可以在运行时动态地访问和调用模块中的函数和成员。这种机制在Web路由、动态配置等场景中非常有用。

五、基础回顾

1. hasattr

用于判断对象中是否存在某个属性或方法。例如:

class Person(object):    def __init__(self, name):        self.name = name    def talk(self):        print("%s正在交谈" % self.name)p = Person("laowang")print(hasattr(p, "talk"))  # True,p有talk方法print(hasattr(p, "name"))  # True,p有name属性print(hasattr(p, "abc"))  # False,p没有abc属性或方法

2. getattr

用于获取对象中的属性或方法的内存地址。例如:

class Person(object):    def __init__(self, name):        self.name = name    def talk(self):        print("%s正在交谈" % self.name)p = Person("laowang")name = getattr(p, "name")  # 获取name属性的内存地址print(name)  # 输出:laowangtalk_method = getattr(p, "talk")  # 获取talk方法的内存地址talk_method()  # 调用talk方法# 如果属性不存在,getattr会返回默认值s = getattr(p, "abc", "not find")print(s)  # 输出:not find

3. setattr

用于为对象添加新的属性或方法。例如:

def abc(self):    print("%s正在交谈" % self.name)class Person(object):    def __init__(self, name):        self.name = namep = Person("laowang")setattr(p, "talk", abc)  # 将abc函数添加到p中,命名为talkp.talk()  # 调用talk方法setattr(p, "age", 30)  # 给p添加一个age属性,值为30print(p.age)  # 输出:30

4. delattr

用于删除对象中的属性。例如:

class Person(object):    def __init__(self, name):        self.name = name    def talk(self):        print("%s正在交谈" % self.name)p = Person("laowang")delattr(p, "name")  # 删除p的name属性print(p.name)  # 会抛出一个AttributeError

这些内置函数为我们提供了对模块内成员进行动态操作的能力,使开发更加灵活和高效。

转载地址:http://djofk.baihongyu.com/

你可能感兴趣的文章
python 之栈的实现
查看>>
python语音播放
查看>>
python语言:装饰器原理
查看>>
Python 交互式数据可视化详解
查看>>
python语言有哪些优点和缺点_Python有哪些优缺点,你了解吗?
查看>>
Python 从入门到精通:30天速成教程到底有多狠?你能坚持下来吗?
查看>>
Python 从数据库中存储和检索密码的最安全方法
查看>>
Python语言及其应用 - 知识点遍历
查看>>
Python 优化提速的 8 个小技巧
查看>>
Python 余弦相似度与皮尔逊相关系数 计算
查看>>
python 使用execjs 报编码错误解决办法,UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xac in position 145: il
查看>>
python 使用filetype校验文件
查看>>
Python 使用flush函数将缓冲区数据立即写磁盘
查看>>
python 使用in判断不准确,in不好使
查看>>
Python 使用pandas 进行查询和统计详解
查看>>
Redis 配置文件redis.conf详细解释
查看>>
python网络爬虫(2)——scrapy框架的基础使用
查看>>
python网络爬虫实例教程试读_Python网络爬虫实战教程(全套完整版) - 学途无忧网 - 做技术的王者 - Powered By EduSoho...
查看>>
Python 使用哈希函数用于加密
查看>>
Python 依赖管理的革新——Poetry 深度解析
查看>>