zoukankan      html  css  js  c++  java
  • 铁乐学python_day23_面向对象进阶1_反射

    铁乐学python_day23_面向对象进阶1_反射

    以下内容大部分摘自博客http://www.cnblogs.com/Eva-J/

    isinstance()和issubclass()

    两者的返回值都是布尔值
    isinstance() 能够检测到继承关系
    type() 只能单纯的判断类
    isinstance() 判断一个对象和一个类有没有血缘关系

    issubclass() 接收两个参数,前一个是子类名,后一个是父类名
    如果返回True,说明有父子(继承)关系。

    isinstance(obj,cls)检查obj是否是类 cls 的对象
    class Foo(object):
         pass
    obj = Foo() # 实例化
    isinstance(obj, Foo)
    
    issubclass(sub, super)检查sub类是否是 super 类的派生类 
    class Foo(object):
        pass
    class Bar(Foo):
        pass
    issubclass(Bar, Foo)
    
    issubclass可以追溯到更远的源头,例如:
    class tuple_A():
        pass
    class grandfather_B(tuple_A):
        pass
    class father_C(grandfather_B):
        pass
    class son_D(father_C):
        pass
    
    print(issubclass(son_D, tuple_A))  # 返回True,是不是很像吸血鬼家族呢?
    

    反射

    1 什么是反射
    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

    2 python面向对象中的反射:
    通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
    四个可以实现自省的函数:
    下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

    1) hasattr(*args, **kwargs)
    def hasattr(*args, **kwargs): # real signature unknown
        """
        Return whether the object has an attribute with the given name.
    
        This is done by calling getattr(obj, name) and catching AttributeError.
        """
        pass
    
    2)getattr(object, name, default=None)
    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
    
    3)setattr(x, y, v)
    def setattr(x, y, v): # real signature unknown; restored from __doc__
        """
        Sets the named attribute on the given object to the specified value.
    
        setattr(x, 'y', v) is equivalent to ``x.y = v''
        """
        pass
    
    4)delattr(x, y)
    def delattr(x, y): # real signature unknown; restored from __doc__
        """
        Deletes the named attribute from the given object.
    
        delattr(x, 'y') is equivalent to ``del x.y''
        """
        pass
    
    has-有;attr-属性; get-得到;set-设置;del-删除。
    
    例:以下有没有办法不通过A.role(类名.静态变量名)就拿到'Preson'这个值呢?
    class A:
        role = 'Preson'
        def func(self, num):
            print('*' * num)
    
    ret = input('>>>')     # 用户输入role
    print(A.__dict__[ret])   # 通过类内置方法__dict__字典[key]的方式可以拿到,但这不是正常行为。
    
    而像 eval(ret) 执行input命令的有严重的安全隐患,不能用!!不然用户输入什么命令你无法控制。
    例如用户输入删除根目录的命令等黑客行为。
    
    那么,这时候使用反射中的getattr方法就可以解决:
    
    print(getattr(A, 'role'))  # 从A的命名空间里找一个属性 ,直接就可以找到这个属性的值
    gettattr 使用字符串数据类型的变量名,访问一个命名空间中的名字(变量名,方法)
    f = getattr(A,'func');f(1)   # 从A的命名空间里找一个方法 ,找到的是这个方法的内存地址
    getattr(A, 'func')(1) # 同理,要想执行类中的方法,也可以使用getattr。等同于A.func(1)执行方法。
    
    在类中的反射 正常情况下如果可以拿到这个变量,
    那么如果有这个变量的字符串形式,就可以用反射获取到这个值。
    找一个属性,直接就可以找到这个属性的值;
    找一个方法,找到的是这个方法的内存地址。
    
    hasattr() 判断某命名空间里有没有某变量名,返回布尔值,
    getattr() 从命名空间中获取字符串数据类型变量名对应的值。
    
    所以hasattr和getattr是一对好朋友,可以先用hasattr进行if判断再getattr执行
    类中的反射--类可以获取类中的属性和方法。
    
    例1:
    class Person():
        role = 'person'
        def __init__(self, name):
            self.name = name
    
        def super_start(self):
            print('巨星指数:'+'*' * 10)
    
    MJ = Person('米高积逊')
    ret = input('>>>').strip()      # 用户交户输入
    if hasattr(MJ, ret):         # 判断假如用户输入的字符串类型变量名存在
        getattr(MJ, ret)()        # 则执行类内部方法
    else:
        print('你的输入有误')       # 条件不成立则不执行,保障了程序运行流畅,不至于卡在getattr这一块报错
    
    例2:
    class Person():
        role = 'person'
        def __init__(self, name):
            self.name = name
    
        def super_start(self):
            print('巨星指数:'+'*' * 10)
    
    MJ = Person('米高积逊')
    print(MJ.super_start) # 打印类内部方法的内存地址
    getattr(MJ, 'super_start')()
    print(getattr(MJ, 'name'))
    setattr(MJ, 'money', 50000000) # 设置属性,若无则新增,若有则修改
    print(MJ.__dict__)
    delattr(MJ, 'money') # 删除属性
    print(MJ.__dict__)
    
    例3:用于模块,可做到接收一个字符串类型变量就执行相应的函数
    def login():
        print('执行login功能')
    
    def register():
        print('执行register功能')
    
    import sys
    print(sys.modules['__main__']) # 打印自身所在py文件(模块)
    
    while 1:
        order = input('>>>').strip()
        if hasattr(sys.modules['__main__'], order):
            getattr(sys.modules['__main__'], order)()
        else:
            print('你输入有误,请重新输入。')
    
    小结
    类使用类命名空间中的名字
        getattr(类名,'名字')
    
    对象使用对象能用的方法和属性
        getattr(对象名,'名字')
    
    模块使用模块中的名字
        导入模块
        getattr(模块名,'名字')
        import os ; getattr(os,'rename')('user','user_info')
    
    从自己所在的模块中使用自己名字
        import sys
        getattr(sys.modules['__main__'],名字)
    

    end
    2018-4-18

  • 相关阅读:
    hdu1240 bfs 水题
    hdu 2102 BFS
    gym 101081E Polish Fortress 几何
    Gym 101081K Pope's work dp
    hdu 6188 贪心
    hdu 6186 水
    Codeforces Round #430 (Div. 2) A B 水 C dfs,思维 D trie,二进制
    hdu6152 拉姆齐定理
    hdu6165 缩点,dfs
    hdu6153 扩展KMP
  • 原文地址:https://www.cnblogs.com/tielemao/p/8877683.html
Copyright © 2011-2022 走看看