zoukankan      html  css  js  c++  java
  • 反射

    反射

    一:isinstance, type, issubclass

    1. issubclass(),这个内置函数可以判断xxx类是否是yyy类的型的子类。
    例:
        class Base:
            pass
        class Foo(Base):
            pass
        class Bar(Foo):
            pass
            
        print(issubclass(Bar,Foo))  # True
        print(issubclass(Foo,Bar))  # False
        print(issubclass(Bar,Base)) # True
        
        
         
        
    
    2. 前面学习过type(),查看obj是由哪个类创建的。
    例:
        class Foo:
            pass
    
        obj = Foo()
        print(obj,type(obj))  # 查看obj的类
         # <__main__.Foo object at 0x00000000024B8160> <class '__main__.Foo'>
        
    
    2.1 现在type()可以判断xxx是否是xxx数据类型的。
    例:
        class Boy:
            pass
        class Girl:
            pass
    
        # 统计传进来的男生和女生分别有多少
        def func(*args):
            b = 0
            g = 0
            for obj in args:
                if type(obj) == Boy:
                    b += 1
                elif type(obj) == Girl:
                    g += 1
            return b, g
        ret = func(Boy(),Girl(),Boy(),Girl(),Boy(),Girl(),Boy(),Girl())
        print(ret)
         # (4,4)
    
    2.2 也可以先判断好数据类型必须是int或者float,进行有意义的计算。
    例:
        def add(a,b):
        if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float):
            return a + b
        else:
            print('报错')    
        
    
    3. isinstance 也可以判断xxx是否是yyy类型的数据,但是isinstance没有typename精准。
    例:
        class Base:
            pass
        class Foo(Base):
            pass
        class Bar(Foo):
            pass
    
        print(isinstance(Foo(),Foo))   # True
        print(isinstance(Foo(),Base))  # True
        print(isinstance(Foo(),Bar))   # False
         
    注:isinstance可以判断该对象是否是xxx家族体系的(只能往上判断,不能往下判断)
    

    二:区分函数和方法

    如何区分函数和方法
    例:
        def func():
            pass
            print(func)   # <function func at 0x0000000002071E18>
                
        
        class Foo:
            def chi(self):
                print('1')
        
        f = Foo()
        print(f.chi)   # <bound method Foo.chi of <__main__.Foo object at 0x00000000024E83C8>>
        
    函数下打印的时候,显示的是function;方法在打印的时候现实的method.
    但其实不一定是这样的。
    例:
        class Foo:
            def chi(self):
                print('我是吃')
    
        @staticmethod
        def ststic_method():
            pass
    
        @classmethod
        def class_method(cls):
            pass
    
        f = Foo()
        print(f.chi)   # <bound method Foo.chi of <__main__.Foo object at 0x00000000024C83C8>>
        print(f.ststic_method)    # <function Foo.ststic_method at 0x00000000022F7950>
        print(f.class_method)     # <bound method Foo.class_method of <class '__main__.Foo'>>
        
        print(Foo.chi) # <function Foo.chi at 0x00000000024F78C8>
        print(Foo.ststic_method)  # <function Foo.ststic_method at 0x00000000024B7950>
        print(Foo.class_method)   # <bound method Foo.class_method of <class '__main__.Foo'>>
        
         注: function 表示是函数
             method 表示是方法
    
    结论:
        1.类方法,不论任何情况都是方法。
        2.静态方法,不论任何情况都是函数。
        3.实例方法,如果是实例(对象)访问就是方法,类名访问就
        
        是函数。
        
        
    如何用程序分辨方法和函数,借助于types模块。
    例:
        # 所有的方法都是MethodType的实例
        #所有的函数都是FunctionType的实例
    
        from types import MethodType ,FunctionType        
        def func():
            pass
    
        # print(isinstance(func,FunctionType))   # True
        # print(isinstance(func,MethodType))     # False
    
    
        class Foo:
            def chi(self):
                print('我是吃')
    
        @staticmethod
        def static_method():
            pass
    
        @classmethod
        def class_method(cls):
            pass
    
        obj = Foo()
        print(type(obj.chi))   # <class 'method'>
        print(type(Foo.chi))   # <class 'function'>
        print(isinstance(obj.chi,MethodType))   # True
        print(isinstance(Foo.chi,FunctionType)) # True
        
        print(isinstance(Foo.static_method,FunctionType))   # False
        print(isinstance(Foo.static_method,MethodType))     # True
        
        print(isinstance(Foo.class_method,MethodType))   # True
        print(isinstance(Foo.class_method,FunctionType)) #  False
            
    注:用types中的FunctionType和MethofType可以区分当前内容是方法还是函数。
    

    三:反射

    例:
        我们需要用别人写的代码,但是我们并不清楚代码中的功能,这时就需要我们自己去测试,来拿到自己想用的功能。
        
        首先拿到 代码:某人.py
        def chi():
            print('某人能吃一头牛')
        def he():
            print('某人能喝一条河')
        def chui():
            print('某人能八天吹破')
        def shui():
            print('某人能睡一年')
    
        # 现在需要自己一个一个的调用,在调用之前已经知道代码中的功能。
    
        import moster
    
        while 1:
            print('''代码中功能有
                chi
                he
                chui
                shui
            大概其就这么多   
            ''')
            gn = input('请输入你想测试的功能:')
            if gn == 'chi':
                master.chi()
            elif gn == 'he':
                master.he()
            elif gn == 'chui':
                master.chui()
            elif gn == 'shui':
                master.shui()
            else:
                print('一共四个功能')
    
    
    现在某人.py文件里有100个功能,我们需要进行100次测试,工程有点浩大。但是我们可以使用反射来简单的完成这个好大的工程,
    如果能通过字符串动态来访问模块中的功能,就能解决这个问题。
    根据上面的操作来进行逆向操作,我们先输入自己想要的功能,然后去代码模块里找,这就叫:反射
    例:
        import moster
        while 1:
            print('''代码中功能有
                chi
                he
                chui
                shui
            大概其就这么多   
            ''')
            gn = input('请输入你想测试的功能:')
            func = getattr(moster,gn)
            func()
        
        
    getattr(对象.字符串): 从对象里获取到xxx功能,此时xxx是一个字符串,get表示找,attr表示属性(功能)。
    但是如果在代码里找不到我想要的内容,就会报错,所以在获取attr之前先判断一下,代码里有没有attr。
    例:
       import master
        from types import FunctionType
    
        while 1:
            print('''代码中功能有
                chi
                he
                chui
                shui
            大概其就这么多   
            ''')
            gn = input('请输入你想测试的功能:')
            if hasattr(master,gn):  # 如果master里有你功能,获取这个功能并执行。
                attr = getattr(master,gn)   # 判断是否是函数,只有函数才可以被调用
                if isinstance(attr,FunctionType):
                    attr()
                else:
                    print(attr)
     
     
    这里讲到两个函数,一个是getattr(),一个是hasattr()。getattr()用来获取信息,hasattr()用来判断xxx中否包含了xxx功能。
    例:
         class Preson:
            country = '大清'
            def chi(self):
                pass
                
        # 类中的内容可以这样动态地进行获取
        print(getattr(Preson,'country'))
        print(getattr(Preson,'chi'))   # 相当于 类名.'静态属性'  函数
    
    
        # 对象一样可以
        obj = Preson()
        print(getattr(obj,'country'))
        print(getattr(obj,'chi'))     # 相当于 对象.'方法名'  方法       
    
    总结:
        getattr可以从模块中获取内容,也可以从类中获取内容,也可以从对象中获取内容。
        在python中一切皆为对象,那就可以认为getattr从对象中动态的获取成员。
    
    
    补充:
    反射一共有4个函数:
        1:getattr(obj.str) 从obj中获取str成员
        2: hasattr(obj.str) 判断obj中是否包含str成员
        3: setattr(obj,str,value) 把obj中的成员设置成value,注:这里的value可以是值,也可以是函数或者方法。
        4:delattr(obj,str) 把obj中的str成员删除
    
    注:以上操作都是在内存中进行,不会影响源代码。
    
    class Foo:
        pass
    
    f = Foo()
    print(hasattr(f,'chi'))  #  False
    
    setattr(f,'chi','123')
    print(f.chi)     # 添加了一个属性信息
    
    setattr(f,'chi',lambda x : x + 1)
    print(f.chi(3))   # 4
    print(f.chi)  # 此时chi既不是静态方法,也不是实例方法,也不是类方法,而是相当于在类中写了一个self.chi = lambda
    print(f.__dict__)  # {'chi': <function <lambda> at 0x0000000002081E18>}
    
    delattr(f,'chi')   #  删除 chi
    print(hasattr(f,'chi'))  #  判断f中是否还包含'chi'   结果:False
  • 相关阅读:
    第十四回 基础才是重中之重~委托实例的几种定义方式(规规矩矩method,逻辑简单delegate,层次清晰lambda)
    第十五回 基础才是重中之重~老赵写的CodeTimer是代码性能测试的利器
    第十一回 基础才是重中之重~Conditional特性使代码根据条件在debug或者release模式中执行
    第十二回 基础才是重中之重~.net中的显式事务与隐式事务
    IE绝对定位元素神秘消失或被遮挡的解决方法
    图片按钮样式隐藏文字的
    javascript 保留小数
    Javascript兼容性问题小结(容易导致浏览器不同,又不容易察觉的)
    SQL 随机选取10条数据
    动态添加类和元素样式属性(style and className)
  • 原文地址:https://www.cnblogs.com/zhao-peng-/p/9833062.html
Copyright © 2011-2022 走看看