4-反射学习

作者: 撸撸很乖张 | 来源:发表于2018-10-13 01:10 被阅读0次

    在python的内置函数中,有这么几个的内置函数 ,分别是:getattr(),setattr(),delattr(),hasattr(),

    这些内置函数主要应用在反射。我们在学习函数的模块的时候,知道在应用第三方模块的时候,首先是要导入才可以使用的,导入使用的是import,那么我们今天使用另外的一种导入方式,也就是__import__,通过它来实现模块中函数的应用,再来引出反射的实际应用。我们创建模块day2,day3,在day2模块中编写login和logout的函数,见代码:

    def login():
        print('我是login函数')
        
    def logout():
        print('我是logout函数')
    

    现在我们实现在day3中调用login和logout的函数,我们不使用import的方式,我们通过__import__的方式,见实现的过程:

    index=__import__('day2')
    
    #调用day2模块中的login函数
    index.login()
    
    #调用day3中logout的函数
    index.logout()
    

    见执行后的输出内容:

    我是login函数
    我是logout函数
    

    依据执行结果,我们可以看到,实现了调用login和调用logout函数的效果,那么在这里,是怎么实现的了?大概可以总结为:

    1、通过__import__的形式导入模块,并赋值给字符串

    2、通过字符串的形式去模块中寻找指定的函数,并执行

    下面我们来通过getattr的方式,来实现如上的实现过程,getattr简单的可以理解为:“依据字符串的形式去模块中寻找指定的目标对象(模块中的函数,或者类中的方法)”,见实现的代码为:

    import  day2
    
    f=getattr(day2,'login')
    
    f()
    

    见执行的结果:

    我是login函数
    

    通过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)
    print('执行目标函数:', target_func())
    

    该代码其实和最初上面的代码实现思想是一致的,就是使用getattr()方法来获取模块中的函数并执行函数。

    其实在开始的时候,已经说了,除了getattr()内置函数外,还有其他的几个内置函数,具体为:

    根据字符串的形式去某个模块中寻找东西--->getattr()
    根据字符串的形式去某个模块中判断东西是否存在--->hasattr()
    根据字符串的形式去某个模块中设置东西---->setattr()
    根据字符串的形式去某个模块中删除东西---->delattr()
    

    如下我们通过一个案例,来引入反射的基本使用。
    commons模块的代码为:

    def index():
        print('index')
    
    def login():
        print('login')
    
    def logout():
        print('logout')
    

    创建一个新的模块,导入commons模块,来调用该模块中编写的方法,见实现的代码:

    import  commons
    
    url=raw_input('请模拟浏览器输入路由:\n')
    
    if url.endswith('index'):
        commons.index()
    elif url.endswith('login'):
        commons.login()
    elif url.endswith('logout'):
        commons.logout()
    else:
        print('Sorry,寻找路由失败')
    

    下面我们通过反射的方式来进行修改,见修改后的代码:

    import  commons
    
    url=raw_input('请模拟浏览器输入路由:\n')
    per=url.split('/')[-1]
    if hasattr(commons,per):
        target_function=getattr(commons,per)
        target_function()
    else:
        print('Not Found 404 Page')
    

    如上的代码修改了很多的,但是还是有一个缺点的,就是我们需要导入模块,但是在实际的工作中,我们基本不清楚路由是来自哪个模块的,需要对如上的代码进行二次重构,重构后的代码为:

    url=raw_input('请模拟浏览器输入路由:\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')
    

    相关文章

      网友评论

        本文标题:4-反射学习

        本文链接:https://www.haomeiwen.com/subject/nxbnaftx.html