潜山云建站网站建设,广州排名网站关键词优化,网络营销案例小故事分享,珠海建站一、前言 1 2 3 4 5 def f1(): print(f1是这个函数的名字#xff01;) s f1 print(%s是个字符串 % s) 在上面的代码中#xff0c;我们必须区分两个概念#xff0c;f1和“f1。前者是函数f1的函数名#xff0c;后者只是一…一、前言 1 2 3 4 5 def f1(): print(f1是这个函数的名字) s f1 print(%s是个字符串 % s) 在上面的代码中我们必须区分两个概念f1和“f1。前者是函数f1的函数名后者只是一个叫”f1“的字符串两者是不同的事物。我们可以用f1()的方式调用函数f1但我们不能用f1()的方式调用函数。说白了就是不能通过字符串来调用名字看起来相同的函数
二、web实例 考虑有这么一个场景根据用户输入的url的不同调用不同的函数实现不同的操作也就是一个url路由器的功能这在web框架里是核心部件之一。下面有一个精简版的示例 首先有一个commons模块它里面有几个函数分别用于展示不同的页面代码如下 1 2 3 4 5 6 7 8 9 10 def login(): print(这是一个登陆页面) def logout(): print(这是一个退出页面) def home(): print(这是网站主页面) 其次有一个visit模块作为程序入口接受用户输入展示相应的页面代码如下这段代码是比较初级的写法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import commons def run(): inp input(请输入您想访问页面的url ).strip() if inp login: commons.login() elif inp logout: commons.logout() elif inp home: commons.home() else: print(404) if __name__ __main__: run() 我们运行visit.py输入home页面结果如下 1 2 请输入您想访问页面的url home 这是网站主页面 这就实现了一个简单的WEB路由功能根据不同的url执行不同的函数获得不同的页面。 然而让我们考虑一个问题如果commons模块里有成百上千个函数呢(这非常正常)?。难道你在visit模块里写上成百上千个elif?显然这是不可能的那么怎么破
三、反射机制 仔细观察visit中的代码我们会发现用户输入的url字符串和相应调用的函数名好像如果能用这个字符串直接调用函数就好了但是前面我们已经说了字符串是不能用来调用函数的。为了解决这个问题python为我们提供一个强大的内置函数getattr!我们将前面的visit修改一下代码如下 1 2 3 4 5 6 7 8 9 10 11 import commons def run(): inp input(请输入您想访问页面的url ).strip() func getattr(commons,inp) func() if __name__ __main__: run() 首先说明一下getattr函数的使用方法它接收2个参数前面的是一个对象或者模块后面的是一个字符串注意了是个字符串 例子中用户输入储存在inp中这个inp就是个字符串getattr函数让程序去commons这个模块里寻找一个叫inp的成员是叫不是等于这个过程就相当于我们把一个字符串变成一个函数名的过程。然后把获得的结果赋值给func这个变量实际上func就指向了commons里的某个函数。最后通过调用func函数实现对commons里函数的调用。这完全就是一个动态访问的过程一切都不写死全部根据用户输入来变化。 执行上面的代码结果和最开始的是一样的。 这就是python的反射它的核心本质其实就是利用字符串的形式去对象模块中操作查找/获取/删除/添加成员一种基于字符串的事件驱动 这段话不一定准确但大概就是这么个意思。
四、进一步完善 上面的代码还有个小瑕疵那就是如果用户输入一个非法的url比如jpg由于在commons里没有同名的函数肯定会产生运行错误具体如下 1 2 3 4 5 6 7 请输入您想访问页面的url jpg Traceback (most recent call last): File F:/Python/pycharm/s13/reflect/visit.py, line 16, in module run() File F:/Python/pycharm/s13/reflect/visit.py, line 11, in run func getattr(commons,inp) AttributeError: module commons has no attribute jpg 那怎么办呢其实python考虑的很全面了它同样提供了一个叫hasattr的内置函数用于判断commons中是否具有某个成员。我们将代码修改一下 1 2 3 4 5 6 7 8 9 10 11 12 import commons def run(): inp input(请输入您想访问页面的url ).strip() if hasattr(commons,inp): func getattr(commons,inp) func() else: print(404) if __name__ __main__: run() 通过hasattr的判断可以防止非法输入错误并将其统一定位到错误页面。 其实研究过python内置函数的朋友应该注意到还有delattr和setattr两个内置函数。从字面上已经很好理解他们的作用了。 python的四个重要内置函数getattr、hasattr、delattr和setattr较为全面的实现了基于字符串的反射机制。他们都是对内存内的模块进行操作并不会对源文件进行修改。
五、基础回顾
hasattr
判断对象中是否有这个方法或变量
class Person(object):def __init__(self,name):self.name namedef talk(self):print(%s正在交谈%self.name)p Person(laowang)
print(hasattr(p,talk)) # True。因为存在talk方法
print(hasattr(p,name)) # True。因为存在name变量
print(hasattr(p,abc)) # False。因为不存在abc方法或变量
getattr
获取对象中的方法或变量的内存地址
class Person(object):def __init__(self,name):self.name namedef talk(self):print(%s正在交谈%self.name)
p Person(laowang)n getattr(p,name) # 获取name变量的内存地址
print(n) # 此时打印的是:laowangf getattr(p,talk) # 获取talk方法的内存地址
f() # 调用talk方法我们发现getattr有三个参数那么第三个参数是做什么用的呢?
s getattr(p,abc,not find)
print(s) # 打印结果not find。因为abc在对象p中找不到本应该报错属性找不到但因为修改了找不到就输出not findsetattr
为对象添加变量或方法
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中并命名为talk
p.talk(p) # 调用talk方法因为这是额外添加的方法需手动传入对象setattr(p,age,30) # 添加一个变量age,复制为30
print(p.age) # 打印结果:30 delattr
删除对象中的变量。注意不能用于删除方法
class Person(object):def __init__(self,name):self.name namedef talk(self):print(%s正在交谈%self.name)p Person(laowang)delattr(p,name) # 删除name变量
print(p.name) # 此时将报错
参考自
https://www.cnblogs.com/kongk/p/8645202.html