美文网首页
Python反射与自省学习

Python反射与自省学习

作者: XYZeroing | 来源:发表于2017-09-06 12:15 被阅读0次

    1.反射自省的概念

    自省:自省就是能够获得自身的结构和方法,给开发者可以灵活的调用,给定一个对象,返回该对象的所有属性和函数列表,或给定对象和该对象的函数或者属性的名字,返回对象的函数或者属性实例。
    反射就是通过字字符串的形式来操作对象或者模块的成员,一种基于字符串的事件驱动。

    2.类与属性

    类是对象的定义,而实例是真正的实物,它存放了类中所定义的对象的具体信息
    类是现实世界的抽象的实体以编程形式出现,实例是这些对象的具体化
    类属性:属性就是一个对象的数据或者函数元素

    class MyNewClass: #所有的类需要至少一个继承,object是所有类的父类
        'define my new class for test' #类的文档,不能被子类继承,可以使用__doc__调出
        version = '1.0'  #类的数据属性
        def __init__(self):  #类似构造器,创建一个新对象时调用,self代表实例对象本身,调用方法时,解释器传给方法
            print('create a object')
        def in_class(self):  #方法,必须绑定到实例才能调用
            print('in class ')
        #申明与定义类同时进行  
    
    myclass = MyNewClass() #实例化
    
    create a object
    
    MyNewClass.version  #访问类数据属性
    
    '1.0'
    
    myclass.version  #访问实例属性
    
    '1.0'
    
    MyNewClass.in_class()  #通过类不能调用方法
    
    ---------------------------------------------------------------------------
    
    TypeError                                 Traceback (most recent call last)
    
    <ipython-input-7-5c59b2c4c0c8> in <module>()
    ----> 1 MyNewClass.in_class()  #通过类不能调用方法
    
    
    TypeError: in_class() missing 1 required positional argument: 'self'
    
    myclass.in_class()  #通过实例进行方法调用
    
    in class 
    
    class MySubClass(MyNewClass):
        'This is my second Class for test'   #文档不能被子类继承
        version = '2.0'
        def __init__(self, num):   #重写__init__方法
            self.num = num
            print('create a sub class ')
        def num_is(self):         #为子类增加方法
            print('The num is %d' % self.num)
    
    my_sub_class = MySubClass(123)  #子类实例化
    
    create a sub class 
    
    my_sub_class.num_is()   #子类方法调用
    
    The num is 123
    
    my_sub_class.in_class()  #访问父类方法
    
    in class 
    
    my_sub_class.version  #子类数据属性
    
    '2.0'
    

    dir()方法,没有参数,返回当前本地作用域中的名称列表。使用参数,尝试返回该对象的有效属性列表

    dir(MyNewClass)   #通过dir()可以查看类的属性
    
    ['__class__',
     '__delattr__',
     '__dict__',
     '__dir__',
     '__doc__',
     '__eq__',
     '__format__',
     '__ge__',
     '__getattribute__',
     '__gt__',
     '__hash__',
     '__init__',
     '__le__',
     '__lt__',
     '__module__',
     '__ne__',
     '__new__',
     '__reduce__',
     '__reduce_ex__',
     '__repr__',
     '__setattr__',
     '__sizeof__',
     '__str__',
     '__subclasshook__',
     '__weakref__',
     'in_class',
     'version']
    

    object.__dict__用于存储对象(可写)属性的字典或其他映射对象,不是所有的对象都有__dict__属性。例如,如果你在一个类中添加了 __slots__属性,那么这个类的实例将不会拥有 __dict__ 属性,但是 dir() 仍然可以找到并列出它的实例所有有效属性

    MyNewClass.__dict__  #类的属性
    
    mappingproxy({'__dict__': <attribute '__dict__' of 'MyNewClass' objects>,
                  '__doc__': 'define my new class for test',
                  '__init__': <function __main__.MyNewClass.__init__>,
                  '__module__': '__main__',
                  '__weakref__': <attribute '__weakref__' of 'MyNewClass' objects>,
                  'in_class': <function __main__.MyNewClass.in_class>,
                  'version': '1.0'})
    
    MyNewClass.__name__   #类名
    
    'MyNewClass'
    
    MyNewClass.__doc__    #查看文档
    
    'define my new class for test'
    
    MySubClass.__doc__
    
    'This is my second Class for test'
    
    MySubClass.__bases__     #查看类的父类的元组
    
    (__main__.MyNewClass,)
    
    MyNewClass.__bases__
    
    (object,)
    
    MyNewClass.__module__   #类定义所在的模块
    
    '__main__'
    
     MyNewClass.__class__
    
    type
    

    2.实例与实例属性

    如果说类是一种很数据结构定义类型,那么实例就是申明了这种类型的变量

    __init__()构造器是最早可以设置实例属性的地方

    class  MyClass (object):
            pass
    
    
    mc = MyClass()
    mc
    
    <__main__.MyClass at 0x7fd26c503198>
    

    如果定义了构造器,它不应返回任何对象,因为实例对象是自动在实例化调用后返回的。
    __init__()就不应该返回任何对象,否则,就可能出现冲突,因为只能返回实例。

    class MyClass(object):
        def __init__(self):
            print('Initialized')
        return 1
    
    mc = MyClass()
    
      File "<ipython-input-29-8544d6773fc1>", line 4
        return 1
        ^
    SyntaxError: 'return' outside function
    

    实例属性

    class C:
        pass
    
    c = C()
    
    c.foo = 'foo foo'
    
    c.bar = 'bar bar'
    
    dir(C)  #类属性
    
    ['__class__',
     '__delattr__',
     '__dict__',
     '__dir__',
     '__doc__',
     '__eq__',
     '__format__',
     '__ge__',
     '__getattribute__',
     '__gt__',
     '__hash__',
     '__init__',
     '__le__',
     '__lt__',
     '__module__',
     '__ne__',
     '__new__',
     '__reduce__',
     '__reduce_ex__',
     '__repr__',
     '__setattr__',
     '__sizeof__',
     '__str__',
     '__subclasshook__',
     '__weakref__']
    
    dir(c)   #实例属性
    
    ['__class__',
     '__delattr__',
     '__dict__',
     '__dir__',
     '__doc__',
     '__eq__',
     '__format__',
     '__ge__',
     '__getattribute__',
     '__gt__',
     '__hash__',
     '__init__',
     '__le__',
     '__lt__',
     '__module__',
     '__ne__',
     '__new__',
     '__reduce__',
     '__reduce_ex__',
     '__repr__',
     '__setattr__',
     '__sizeof__',
     '__str__',
     '__subclasshook__',
     '__weakref__',
     'bar',
     'foo']
    
    c.__dict__ 
    
    {'bar': 'bar bar', 'foo': 'foo foo'}
    
    class T:
        pass
    
    t = T()
    
    t.__dict__
    
    {}
    
    t.__class__
    
    __main__.T
    

    类属性和实例属性:类属性仅是与类相关的数据值,这些值可以像静态成员那样被引用,即使在多次实例化中调用类,他们的值都保持不变

    class T(object):
        version = 1.0
    
    t = T()  #实例化
    
    T.version  #访问类属性
    
    1.0
    
    t.version  #访问实例属性
    
    1.0
    
    t.version = 2.0  #改变实例属性(实际上时床架了新的实例属性),而非类属性
    
    t.version
    
    2.0
    
    T.version   #类属性没有改变
    
    1.0
    
    del t.version  #删除实例属性, 给一个与类属性同名的实例属性赋值,我们会有效的“隐藏”类属性,删除又重现
    
    t.version
    
    1.0
    
    T.version = 3.0  #更新类属性
    
    t.version   #实例访问,其值已经改变
    
    3.0
    

    但是在类属性可以改变的情况下,类属性可以通过实例改变

    class Foo(object):
         x = {2003: 'poe2'}
    
    foo = Foo()
    
    foo.x
    
    {2003: 'poe2'}
    
    foo.x[2004] = 'valid path'   #通过实例改变
    
    foo.x
    
    {2003: 'poe2', 2004: 'valid path'}
    
    Foo.x   #类属性已经改变
    
    {2003: 'poe2', 2004: 'valid path'}
    

    3.绑定和方法调用

    方法仅仅是类内部定义的函数,这意味着方法时类属性而不是实例属性
    任何方法定义的第一个参数都是变量self,它表示调用此方法的实例对象

    非绑定方法:需要调用一个还没有任何实例的类中的一个方法

    class Person(object):
        def __init__(self, name):
            self.name = name
        def get_name(self):
            return('The name is %s' % self.name)
    
    Person.get_name
    
    <function __main__.Person.get_name>
    
    Person.get_name()   #方法未绑定
    
    ---------------------------------------------------------------------------
    
    TypeError                                 Traceback (most recent call last)
    
    <ipython-input-66-257ab8eff3fa> in <module>()
    ----> 1 Person.get_name()   #方法未绑定
    
    
    TypeError: get_name() missing 1 required positional argument: 'self'
    
    Person.get_name(Person('zhang'))  #未绑定的方法必须使用一个Person实例作为第一个参数来调用
    
    'The name is zhang'
    
    p = Person('python')  #实例化绑定方法,使用实例调用,调用的实例被作为第一个参数被隐含的传递过去
    
    print(p)
    
    <__main__.Person object at 0x7fd26c505ac8>
    

    4.内建函数

    hasattr、getattr、setattr、delattr:对象是否有、取得、设置、删除某个属性

    class TestAttr(object):
        def __init__(self):
            self.foo = 100
    
    ta = TestAttr()
    
    hasattr(ta, 'foo')  #判断是否具有'foo'属性
    
    True
    
    getattr(ta, 'foo')  #取得foo的值
    
    100
    
    getattr(ta, 'bar')  #取得bar的值,但是对象没有该值,抛出异常
    
    ---------------------------------------------------------------------------
    
    AttributeError                            Traceback (most recent call last)
    
    <ipython-input-80-f6c57b29833a> in <module>()
    ----> 1 getattr(ta, 'bar')  #取得bar的值,但是对象没有该值,抛出异常
    
    
    AttributeError: 'TestAttr' object has no attribute 'bar'
    
    setattr(ta, 'bar', 100000)  #设置某个值
    
    getattr(ta, 'bar')
    
    100000
    
    setattr(ta, 'my attr', 'Python Class Attr Function')
    
    dir(ta)
    
    ['__class__',
     '__delattr__',
     '__dict__',
     '__dir__',
     '__doc__',
     '__eq__',
     '__format__',
     '__ge__',
     '__getattribute__',
     '__gt__',
     '__hash__',
     '__init__',
     '__le__',
     '__lt__',
     '__module__',
     '__ne__',
     '__new__',
     '__reduce__',
     '__reduce_ex__',
     '__repr__',
     '__setattr__',
     '__sizeof__',
     '__str__',
     '__subclasshook__',
     '__weakref__',
     'bar',
     'foo',
     'my attr']
    
    delattr(ta, 'bar')  #删除某个值
    
    delattr(ta, 'foo')
    
    ta.__dict__
    
    {'my attr': 'Python Class Attr Function'}
    

    相关文章

      网友评论

          本文标题:Python反射与自省学习

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