博客
关于我
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 利用pandas读取本地中CSV文件的指定列 列名重命名 并保存回本地
查看>>
python 利用pyspark读取HDFS中CSV文件的指定列 列名重命名 并保存回HDFS
查看>>
python 利用pyttsx3文字转语音
查看>>
python 利用已有Ner模型进行数据清洗合并
查看>>
python 到大数据开发工程师_如何成为一个大数据开发工程师?
查看>>
python 加密解密(base64, AES)
查看>>
Python 包管理器和 Node.js
查看>>
Python 单词字母顺序不变且所有倒排
查看>>
python 反射机制
查看>>
python 启动提示IDLE's subprocess didn't make conne...
查看>>
python 命令接口_实现“[命令][操作][参数]”样式的命令行接口?
查看>>
Python 和 OpenCV.如何检测图像中的所有(填充)圆形/圆形对象?
查看>>
Python 和 RabbitMQ - 聆听来自多个渠道的消费事件的最佳方式?
查看>>
python编辑器打不开_关于命令ride.py打不开RF,而是打开pycharm编辑器问题解决思路...
查看>>
python编译exe同时支持32位_第三周:同时管理64位和32位版本的Python,并用Pyinstaller打包成exe...
查看>>
Python 和Java 哪个更适合做自动化测试?
查看>>
Python编程:掌握高级语言程序设计。从零基础到精通,收藏这篇就够了!
查看>>
python 图片转ico
查看>>