博客
关于我
python 反射机制
阅读量:804 次
发布时间: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 unittest高级特性!
查看>>
Python unittest:如何将标准输出消息临时重定向到缓冲区并测试其内容?
查看>>
Python urllib/Requests下载文件失败,但浏览器下载失败
查看>>
Python urllib2 文件上传问题
查看>>
Python urllib2.open 连接由对等错误重置
查看>>
python urllib2详解及实例
查看>>
Python url请求提示certificate verify failed unable to get local issuer certificate
查看>>
Python UTC 日期时间对象的 ISO 格式不包括 Z(祖鲁语或零偏移)
查看>>
python valueerror object2_python遇到错误记录
查看>>
python vars的作用
查看>>
Python vcrpy库:HTTP请求记录和重放
查看>>
Python virtualenv
查看>>
python vue3实现大文件分段续传(断点续传)--带暂停和继续功能
查看>>
Python WebDriver如何打印整个页面源(html)
查看>>
Python WebSocket自动化测试:构建高效接口测试框架
查看>>
Python Web开发
查看>>
Redis 配置文件杂项。
查看>>
Python web自动化测试 —— 文件上传
查看>>
Python web自动化测试 —— 文件上传!
查看>>
Python Web自动化测试开发环境搭建(附安装包与虚拟机环境)
查看>>