• python-面向对象-反射


    isinstance 和 issubclass

    isinstance(obj,cls)检查是否obj是否是类的cls的对象

    class Test:
        def __init__(self, var):
            self.var = var
    
        def show(self):
            print("哈哈!")
    
    
    t = Test('test')
    a = 'test'
    
    print(isinstance(t, Test))  # True
    print(isinstance(a, Test))  # False
    
    

    isinstance和type区别

    class Test(object): pass
    
    
    class Test_son(Test): pass
    
    
    t1 = Test()
    t2 = Test_son()
    print(isinstance(t2, Test))  # True  # 承认继承关系
    print(type(t2) is Test)  # False   # 不承认继承关系
    
    a = 10
    
    print(type(a) is int)  # True
    print(isinstance(a, int))  # True
    
    
    # isinstance(obj,类)
        # 承认继承关系的
    # 类 = type(obj)
        # 只承认实例化这个对象的那个类(不承认所有的继承关系)
    
    

    issubclass(sub,super)检查sub类是否是super类的派生类

    class Test:
        def __init__(self, var):
            self.var = var
    
        def show(self):
            print("哈哈!")
    
    
    class Test1(Test):
        pass
    
    
    print(issubclass(Test1, Test))  # True
    
    

    反射

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。python面向对象中的反射:通过字符串的形式操作对象相关的属性

    • hasattr 检测是否含有某个属性
    • gatattr 获取属性
    • setattr 设置属性
    • delattr 删除属性
    class Foo:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def show(self):
            print("哈哈哈!")
    
    
    obj = Foo("Tom", 14)
    
    #检测某个属性
    
    print(hasattr(obj, 'age'))  # True
    print(hasattr(obj, 'sex'))  # False
    print(hasattr(obj, 'show'))  # True
    
    
    # 获取属性
    
    print(getattr(obj,'age'))  # 14
    print(getattr(obj,'show'))  # <bound method Foo.show of <__main__.Foo object at 0x0000025D610AF940>>
    # print(getattr(obj, 'sex'))  # error AttributeError: 'Foo' object has no attribute 'sex'
    
    
    # 修改属性
    
    print(obj.__dict__)  # {'name': 'Tom', 'age': 14}
    print(setattr(obj, 'sex', "male"))
    print(obj.__dict__)  #{'name': 'Tom', 'age': 14, 'sex': 'male'}
    
    print(setattr(obj, 'name', "Yang"))
    print(obj.__dict__)  # {'name': 'Yang', 'age': 14, 'sex': 'male'}
    
    
    # 删除属性
    print(obj.__dict__)  # {'name': 'Yang', 'age': 14, 'sex': 'male'}
    print(delattr(obj, "name"))
    print(obj.__dict__)  # {'age': 14, 'sex': 'male'}
    
    print(delattr(obj,'func'))  # Error AttributeError: func
    
    

    反射的详细说明:

    看下面的代码,是没有使用反射的

    class Manager:  # 管理员用户
        def __init__(self, name):
            self.name = name
    
        def create_course(self):  # 创建课程
            print('in Manager create_course')
    
        def create_student(self):  # 给学生创建账号
            print('in Manager create_student')
    
        def show_courses(self):  # 查看所有课程
            print('in Manager show_courses')
    
        def show_students(self):  # 查看所有学生
            print('in Manager show_students')
    
    
    # 不用反射
    tim = Manager('Tim')
    operate_lst = ['创建课程', '创建学生账号', '查看所有课程', '查看所有学生']
    for index, opt in enumerate(operate_lst, 1):
        print(index, opt)
    num = input('请输入您要做的操作 :')
    if num.isdigit():
        num = int(num)
    if num == 1:
        tim.create_course()
    elif num == 2:
        tim.create_student()
    elif num == 3:
        tim.show_courses()
    elif num == 4:
        tim.show_students()
    
    
    

    使用反射之后:

    tim = Manager('Tim')
    
    operate_lst = [('创建课程', 'create_course'), ('创建学生账号', 'create_student'),
                   ('查看所有课程', 'show_courses'), ('查看所有学生', 'show_students')]
    for index, opt in enumerate(operate_lst, 1):
        print(index, opt[0])
    num = input('请输入您要做的操作 :')
    if num.isdigit():
        num = int(num)
        if hasattr(tim, operate_lst[num - 1][1]):
            getattr(tim, operate_lst[num - 1][1])()
    
    

    如果使用反射呢?

    # 对象名.属性名 / 对象名.方法名() 可以直接使用对象的方法和属性
    # 当我们只有字符串数据类型的内容的时候
        # getattr(对象名,'方法名')()
        # getattr(对象名,'属性名')
    

    类反射

    class A(object):
        Country = "China"
    
        @classmethod
        def show(cls):
            print("国家:", cls.Country)
    
    
    getattr(A, "show")()  # 等价于A.show()
    print(getattr(A, "Country"))  # 等价于print(A.Country)
    

    反射在模块中

    import re
    
    res = re.findall("d+", "1abcdef123a123")
    print(res)  # ['1', '123', '123']
    
    # 使用反射
    res1 = getattr(re, 'findall')("d+", "1abcdef123a123")
    print(res1)  # ['1', '123', '123']
    
    # getattr(re,'findall') 等价于re.findall
    
    import time
    
    now = time.time()
    print(now)  # 1554102738.7555645
    res = getattr(time, "time")()
    print(res)  # 1554102738.7555645
    
    # getattr(time, "time") 等价于time.time
    
    # 只要是a.b这种结构,都可以使用反射
    # 用对象类模块反射,都只有以下场景
    # 这种结构有两种场景
        # a.b   b是属性或者变量值
            # getattr(a,'b')   == a.b
        # a.b()  b是函数或者方法
            # a.b()
                # getattr(a,'b')()
            # a.b(arg1,arg2)
                # getattr(a,'b')(arg1,arg2)
            # a.b(*args,**kwargs)
                # getattr(a,'b')(*args,**kwargs)
    
    

    反射在当前文件中的使用

    怎么样查看本文件下的a变量,func函数。而不是使用打印的方式。

    def func():
        print("func")
    
    a = 999
    

    解决这个问题,需要导入内置的模块,sys,在sys中的modules方法,就所以的模块列举出来。

    from sys import modules
    print(modules)
    

    20190401152836.png

    上图片中标注出来的就当前的文件,则就可通过字典进行访问,而key就是"__main__",在访问当前的文件,也可以直接使用__name__。

    print(__name__)  # __main__  打印__name___ 直接是__main__
    
    
    from sys import modules
    a = 999
    
    def func():
        print("func")
    
    
    print(modules['__main__'].a)  # 999
    modules["__main__"].func()  # func
    
    print(modules[__name__].a)  # 999
    modules[__name__].func()  # func
    
    
    from sys import modules
    
    a = 999
    
    
    def func():
        print("func")
    
    
    class Test(object):
        Country = "China"
    
        @classmethod
        def show(cls):
            print("国家:", cls.Country)
    
    
    # print(modules['__main__'].a)  # 999
    # modules["__main__"].func()  # func
    #
    # print(modules[__name__].a)  # 999
    # modules[__name__].func()  # func
    if hasattr(modules[__name__], 'a'):
        print(getattr(modules[__name__], 'a'))  # 999
    if hasattr(modules[__name__], 'func'):
        getattr(modules[__name__], 'func')()
    
    if hasattr(modules[__name__], 'Test'):
        print(Test)  # <class '__main__.Test'>
        print(getattr(modules[__name__], 'Test'))  # <class '__main__.Test'>
        print(getattr(modules[__name__], 'Test').Country)  # China
        getattr(modules[__name__], 'Test').show()  # 国家: China
    

    setattr

    能够通过字符串数据类型的变量名 给一个对象创建一个新的属性

    class A(object):
        def func(self):
            print("func")
    
    
    a = A()
    print(a.__dict__)  # {}
    a.name = "Tom"
    setattr(a, "name1", "Jack")  # 相当于a.name1 = "Jack"
    print(a.__dict__) # {'name': 'Tom', 'name1': 'Jack'}
    
    

    deltattr

    print(a.__dict__)  # {'name': 'Tom', 'name1': 'Jack'}
    delattr(a, 'name1')
    print(a.__dict__)  # {'name': 'Tom'}
    del a.name
    print(a.__dict__)  # {}
    
    

    总结:

    # hasattr和getattr
        # 只要是a.b这种结构,都可以使用反射
        # 用对象类模块反射,都只有以下场景
        # 这种结构有两种场景
        #     a.b   b是属性或者变量值
        #         getattr(a,'b')   == a.b
        #     a.b()  b是函数或者方法
        #         a.b()
        #             getattr(a,'b')()
        #         a.b(arg1,arg2)
        #             getattr(a,'b')(arg1,arg2)
        #         a.b(*args,**kwargs)
        #             getattr(a,'b')(*args,**kwargs)
        # 如果是本文件中的内容,不符合a.b这种结构
            # 直接调用func()
                # getattr(sys.modules[__name__],'func')()
            # 直接使用类名 Person()
                # getattr(sys.modules[__name__],'Person')()
            # 直接使用变量名 print(a)
                # getattr(sys.modules[__name__],'a')
        # 所有的getattr都应该和hasattr一起使用
            # if hasattr():
                 getattr()
    # setattr 只用来修改或者添加属性变量,不能用来处理函数或者是其他方法
        # a.b = value
        # setattr(a,'b',value)
        
    # delattr 只用来删除 属性变量
        # del a.b 删除属性  相当于删除了a对象当中的b属性
        # delattr(a,'b')
    
  • 相关阅读:
    【转】Google 的眼光
    【转】不要去SeaWorld
    【转】Tesla Autopilot
    【转】Tesla Model X的车门设计问题
    【转】Tesla Model S的设计失误
    【转】编程的智慧
    【转】智商的圈套
    【转】创造者的思维方式
    【转】恶评《星际穿越》
    【转】谈创新
  • 原文地址:https://www.cnblogs.com/yangchangjie150330/p/10636997.html
Copyright © 2020-2023  润新知