python的反射学习(十四)
在python的内置函数中,有这么几个的内置函数 ,分别是:getattr(),setattr(),delattr(),hasattr(),
这些内置函数主要应用在反射。我们在学习函数的模块的时候,知道在应用第三方模块的时候,首先是要导入
才可以使用的,导入使用的是import,那么我们今天使用另外的一种导入方式,也就是__import__,通过它
来实现模块中函数的应用,再来引出反射的实际应用。
我们创建模块day2,day3,在day2模块中编写login和logout的函数,见代码:
#!/usr/bin/env python #coding:utf-8 def login(): print '我是login函数' def logout(): print '我是logout函数'
现在我们实现在day3中调用login和logout的函数,我们不使用import的方式,我们通过__import__
的方式,见实现的过程:
#!/usr/bin/env python # -*- coding:utf-8 -*- index=__import__('day2') #调用day2模块中的login函数 index.login() #调用day3中logout的函数 index.logout()
见执行后的输出内容:
C:\Python27\python.exe D:/git/Python/FullStack/share/day3.py
我是login函数
我是logout函数
Process finished with exit code 0
依据执行结果,我们可以看到,实现了调用login和调用logout函数的效果,那么在这里,是怎么实现的了?大概可以总结为:
1、通过__import__的形式导入模块,并赋值给字符串
2、通过字符串的形式去模块中寻找指定的函数,并执行
下面我们来通过getattr的方式,来实现如上的实现过程,getattr简单的可以理解为:“依据字符串的形式去模块中寻找
指定的目标对象(模块中的函数,或者类中的方法)”,见实现的代码为:
#!/usr/bin/env python # -*- coding:utf-8 -*- import day2 f=getattr(day2,'login') f()
见执行的结果:
C:\Python27\python.exe D:/git/Python/FullStack/share/day3.py
我是login函数
Process finished with exit code 0
通过getattr()的方式更加简单,它的第一个参数是对象模块,第二个参数是指定的模块,最后一个是默认参数None,见
getattr()方法的源码:
def getattr(object, name, default=None): # known special case of getattr """ getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case. """ pass
如上的形式,可以总结为:通过字符串的形式,来寻找模块中的函数并执行函数。粗暴的实现为:
import day2 inp_func=raw_input(u'请输入要执行的函数:\n') target_func=getattr(day2,inp_func) u'执行目标函数:', target_func()
该代码其实和最初上面的代码实现思想是一致的,就是使用getattr()方法来获取模块中的函数并执行函数。
其实在开始的时候,已经说了,除了getattr()内置函数外,还有其他的几个内置函数,具体为:
根据字符串的形式去某个模块中寻找东西--->getattr()
根据字符串的形式去某个模块中判断东西是否存在--->hasattr()
根据字符串的形式去某个模块中设置东西---->setattr()
根据字符串的形式去某个模块中删除东西---->delattr()
下面我们完善下day2模块,里面编写一个类,一个变量,来逐步的说明下如上几个内置函数的使用,见完善后的day2
模块的代码:
#!/usr/bin/env python
#coding:utf-8
def login():
print '我是login函数'
def logout():
print '我是logout函数'
django='Hello Django!'
class Person:
def __init__(self):
pass
def info(self):
print 'info'
先来实现获取模块中的变量,见实现的代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import day2
f=getattr(day2,'django')
print u'模块中的变量为:{0}'.format(f)
执行后的输出结果为:
C:\Python27\python.exe D:/git/Python/FullStack/share/day3.py
模块中的变量为:Hello Django!
Process finished with exit code 0
现在通过getattr()来获取类中方法并执行该方法,思路是首先需要类进行实例化,然后再依据getattr()进行,见
实现的代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import day2
#对类进行实例化
obj=day2.Person()
f=getattr(obj,'info')
f()
执行方法这里不写了,感兴趣的同学可以执行下看下输出的结果内容。
hasattr()是判断属性是否存在,比如判断类中是否存在一个方法,存在返回的是true,不存在返回的是flase,见
实现的代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import day2
#对类进行实例化
obj=day2.Person()
f=hasattr(obj,'info')
print f
setattr是设置属性在模块中的内容,下面我们来实现在类中设置一个属性,见实现的代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import day2
#对类进行实例化
obj=day2.Person()
f=hasattr(obj,'login')
print u'login方法在类中是否存在:{0}'.format(f)
#在类中设置login方法
setattr(obj,'login','this is a login method')
f=hasattr(obj,'login')
print u'login方法在类中是否存在:{0}'.format(f)
getattr(obj,'login')
print u'login方法执行的结果为:{0}'.format(getattr(obj,'login'))
delattr是删除模块中的属性,见实现的代码:
#!/usr/bin/env python #coding:utf-8 import commons delattr(commons,'framework') print u'验证模块中的变量是否被删除:',hasattr(commons,'framework')
如下我们通过一个案例,来引入反射的基本使用。
commons模块的代码为:
#!/usr/bin/env python #coding:utf-8 def index(): print 'index' def login(): print 'login' def logout(): print 'logout'
创建一个新的模块,导入commons模块,来调用该模块中编写的方法,见实现的代码:
#!/usr/bin/env python #coding:utf-8 import commons url=raw_input(u'请模拟浏览器输入路由:\n') if url.endswith('index'): commons.index() elif url.endswith('login'): commons.login() elif url.endswith('logout'): commons.logout() else: print u'Sorry,寻找路由失败'
下面我们通过反射的方式来进行修改,见修改后的代码:
#!/usr/bin/env python #coding:utf-8 import commons url=raw_input(u'请模拟浏览器输入路由:\n') per=url.split('/')[-1] if hasattr(commons,per): target_function=getattr(commons,per) target_function() else: print 'Not Found 404 Page'
如上的代码修改了很多的,但是还是有一个缺点的,就是我们需要导入模块,但是在实际的工作中,我们基本不清楚路由
是来自哪个模块的,需要对如上的代码进行二次重构,重构后的代码为:
#!/usr/bin/env python #coding:utf-8 url=raw_input(u'请模拟浏览器输入路由:\n') target_models,target_function=url.split('/') m=__import__(target_models) if hasattr(m,target_function): target_function=getattr(m,target_function) target_function() else: print 'Not Found 404 Page'
如您对我写的内容感兴趣,可扫描如下二维码关注我的微信公众号,谢谢!!!