本文共 2846 字,大约阅读时间需要 9 分钟。
在前面的代码中,我们区分了f1和“f1”两个概念。前者是函数f1的名字,后者是一个字符串。我们不能直接用"f1"调用函数,但可以通过f1()的方式调用。这种区别提醒我们,字符串和函数名虽然看起来相似,但本质上是不同的东西。
在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页面,避免了错误的发生。
总结一下,getattr和hasattr这两个内置函数为我们提供了强大的反射能力,可以在运行时动态地访问和调用模块中的函数和成员。这种机制在Web路由、动态配置等场景中非常有用。
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属性或方法 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 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 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/