• Python--反射


    在python中,给你一个函数或者类的字符串名称,你怎么得到该函数和类,以下方式:
    1.通过getattr获取方法名,再运行
    class TestA(object):
        def get_test(self):
            print("我是函数1")
    
        def instance(self):
            print("我是函数2")
    
    ins = TestA()
    get_test = getattr(ins, "get_test")   # 通过python的反射方法getattr达到我们想要的结果
    get_test()
    我们运行得到结果:
    我是函数1
     
    让我们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
    根据源码解释getattr函数需要我们传一个对象,和一个字符串,然后从对象中找到和字符串同名的方法属性。
    当然跟getattr相同的反射方法有,setattr和delattr,顾名思义这里不多解释。
     
    2.通过eval函数
    class TestA(object):
        def get_test(self):
            print("我是函数1")
    
        def instance(self):
            print("我是函数2")
    
        @staticmethod
        def test3():
            print("我是静态方法")
    
    ins = TestA()
    instance = getattr(TestA, "instance")
    instance(ins)
    print("---------------2---------------------")
    eval("instance")(ins)
    print("-----------------3-------------------")
    eval("TestA").test3()
    得到我们想要的结果,那我们就好奇eval函数是怎么实现可以传入一个字符串就去寻找对应的函数或者类对象,我们看一下eval函数的源码
    def eval(source, globals=None, locals=None): # real signature unknown; restored from __doc__
        """
        eval(source[, globals[, locals]]) -> value
        
        Evaluate the source in the context of globals and locals.
        The source may be a string representing a Python expression
        or a code object as returned by compile().
        The globals must be a dictionary and locals can be any mapping,
        defaulting to the current globals and locals.
        If only globals is given, locals defaults to it.
        """
        pass
    我们根据源码解释,首先解释器会我们传入的去locals和globals中去找我们传入的source为键找对应的值,如果未传入globals和locals就会去默认的glocals和locals中寻找,然后我们就好奇这个globals和locals是什么,然后我们运行一下
    def globals(): # real signature unknown; restored from __doc__
        """
        globals() -> dictionary
        
        Return the dictionary containing the current scope's global variables.
        """
        return {}
    
    def locals(): # real signature unknown; restored from __doc__
        """
        locals() -> dictionary
        
        Update and return a dictionary containing the current scope's local variables.
        """
        return {}
    看源码解释,globals为返回一个包含全局变量的字典,locals为返回一个包含本地变量的字典,然后运行这两个函数,看一下结果:
     
    3.通过globals函数
    globals()函数运行的结果为一个字典,类对象的字符串为建,类对象为值,所以我们可以这样得到:
    class TestA(object):
        a=1
        def get_test(self):
            print("我是函数1")
    
        def instance(self):
            print("我是函数2")
    
        @staticmethod
        def test3():
            print("我是静态方法")
    
    
    globals()["TestA"].test3()
    结果:
    我是静态方法
     
    4.通过标准库operator中methodcaller方法
    from operator import methodcaller
      
    class Circle(object):
        def __init__(self, radius):
            self.radius = radius
       def getArea(self):
            return round(pow(self.radius, 2) * pi, 2)
     
    class Rectangle(object):
        def __init__(self, width, height):
             self.width = width
             self.height = height
    
        def get_area(self):
              return self.width * self.height
      
    if __name__ == '__main__':
     c1 = Circle(5.0)
     r1 = Rectangle(4.0, 5.0)
       
     # 第一个参数是函数字符串名字,后面是函数要求传入的参数,执行括号中传入对象
     erea_c1 = methodcaller('getArea')(c1)
     erea_r1 = methodcaller('get_area')(r1)
     print(erea_c1, erea_r1)
     

  • 相关阅读:
    JS身份证真实性校验(一)
    Python之文件操作
    python之数据类型
    Python之循环条件、变量、字符串格式化
    webpack之proxyTable设置跨域
    vue报错解决方案
    CentOS 7 下Ansiable搭建命令列表 及常用监控指令
    CentOS 7 下nagios搭建记录
    弹窗鼠标拖动功能-js
    做好探索性测试,体现你的价值
  • 原文地址:https://www.cnblogs.com/absoluteli/p/14090117.html
Copyright © 2020-2023  润新知