zoukankan      html  css  js  c++  java
  • 你真的百分之百熟悉python中的魔法属性吗

    楔子

    作为动态语言,python里面提供了很多以双下划线:__开头和结尾的属性,我们称之为魔法属性,这些属性是对象所内置的。我们可以直接通过这些魔法属性动态地查看一个对象的信息,下面我们就来看一看。

    __name__

    __name__是用来获取一个对象的名字的

    print(int.__name__)  # int
    print(type.__name__)  # type
    
    
    def foo(): pass
    
    
    print(foo.__name__)  # foo
    
    
    class A:
        pass
    
    
    print(A.__name__)  # A
    print(object.__name__)  # object
    
    
    import sys
    print(sys.__name__)  # sys
    
    import pandas as pd
    print(pd.__name__)  # pandas
    

    我们看到类、函数、模块都具有__name__属性,但是注意:实例对象没有__name__属性,比如:123、"string"、{"a": 111}。

    这里提一下__name__和__qualname__

    估计有人不清楚这个 __qualname__ 是做什么的,这个 __qualname__ 称之为全限定名。

    print(str.__name__)  # str
    print(str.__qualname__)  # str
    
    print(str.join.__name__)  # join
    print(str.join.__qualname__)  # str.join
    
    
    class A:
        class B:
            def foo(self):
                pass
    
    print(A.B.foo.__name__)  # foo
    print(A.B.foo.__qualname__)  # A.B.foo
    
    import tornado.web
    print(tornado.web.RedirectHandler.write.__name__)  # write
    print(tornado.web.RedirectHandler.write.__qualname__)  # RequestHandler.write
    

    对于类、模块、函数(直接在全局使用def定义)来说,这两者没什么区别,但如果是类里面的函数的话,那么 __name__ 获取的还是函数名,但是 __qualname__ 则是包含了所在的类名(可以是多个)。并且这个 __qualname__ 最多扩展到类,不会显示所在模块。

    __doc__

    __doc__ 就很简单了,就是获取一个对象的文档注释。

    class A:
        """
        这个是一个类
        名叫class A
        """
    
        def __init__(self):
            """
            这是构造函数
            """
    
    
    print(A.__doc__)
    """
    
        这个是一个类
        名叫class A
        
    """
    print(A.__init__.__doc__)
    """
    
            这是构造函数
         
    """
    

    __doc__ 会将格式原原本本地输出出来,并且,类的实例对象也是可以获取 __doc__ 属性的。

    __base__

    查看一个类都继承了哪些类。

    class A:
        pass
    
    
    class B(int, A):
        pass
    
    
    print(B.__base__)  # <class 'int'>
    
    """
    但是我们看到__base__只显示继承的类的其中一个
    那么有没有办法全部显示呢?
    答案是使用__bases__
    """
    print(B.__bases__)  # (<class 'int'>, <class '__main__.A'>)
    
    print(A.__base__)  # <class 'object'>
    print(A.__bases__)  # (<class 'object'>,)
    
    """
    我们看到,如果显式地继承了某个类,会打印继承的类的名字
    如果没有,那么打印object
    """
    

    对于 __base__ 和 __bases__ 两个魔法属性,只有类才具有,实例对象是没有的。

    __class__

    显示一个对象类型,换句话说就是显示自己是被谁实例化的。而 python 中的任何对象都有 __class__ 属性,因为我们说 python 中一切皆对象,那么就必定有一个类能够实例化它。

    print("".__class__)  # <class 'str'>
    print({}.__class__)  # <class 'dict'>
    print([].__class__)  # <class 'list'>
    print(int.__class__)  # <class 'type'>
    print(object.__class__)  # <class 'type'>
    print(type.__class__)  # <class 'type'>
    

    __module__

    显示一个对象所在的模块

    print(str.__module__)  # builtins
    
    from tornado.web import RedirectHandler
    print(RedirectHandler.__module__)  # tornado.web
    
    
    import numpy
    print(numpy.ndarray.__module__)  # numpy
    from numpy.core._multiarray_umath import ndarray
    print(ndarray.__module__)  # numpy
    
    print(getattr.__module__)  # builtins 
    

    类、或者在全局定义的函数具有 __module__ 属性,另外我们看一下 numpy,我们说 ndarray 这个类实际上位于 numpy.core._multiarray_umath 中,但是它在我们加载 numpy 的时候,就已经在__init__.py 中被加载进来了,所以显示的是 numpy。

    __dict__

    这个表示属性字典,我们说类、函数、实例对象都有自己的属性字典,这个属性我个人觉得就没有必要介绍了,因为属性字典肯定都非常熟悉了

    __file__

    __file__ 这个属性,只有模块才具有。我们这里的模块指的不单单是一个文件,一个具有多个文件的目录也可以是一个模块。在底层,单独的文件和一个目录都可以作为模块,都对应PyModuleObject对象。

    import datetime
    print(datetime.__file__)  # C:python38libdatetime.py
    
    import tornado
    print(tornado.__file__)  # C:python38libsite-packages	ornado\__init__.py
    
    """
    我们说对于单独的文件所构成的模块来讲,它的__file__就是其文件所在的绝对路径
    如果是目录所构成的模块,那么__file__就是内部的__init__.py的绝对路径
    """
    
    from pandas import core
    print(core.__file__)  # C:python38libsite-packagespandascore\__init__.py
    
    # 这个时候问题来了,如果这个目录没有__init__.py文件怎么办?
    import 空目录
    print(空目录.__file__)  # None
    # 如果没有的话,那么显示的为None
    

    另外,有一些模块属于特例,像sys、time这些内嵌在解释器里面的模块是不具备__file__属性的。

    __path__

    __path__ 属性还是只有模块才有,并且这个模块必须是有目录所构成的模块。我们说单独的文件和目录都可以作为模块,但是只有目录对应的模块才具有 __path__ 属性。

    from pandas import core
    print(core.__path__)  # ['C:\python38\lib\site-packages\pandas\core']
    
    import tornado
    print(tornado.__path__)  # ['C:\python38\lib\site-packages\tornado']
    """
    这里的__path__打印的是对应目录的绝对路径
    """
    
    import 空目录
    print(空目录.__path__)  # _NamespacePath(['D:\satori\空目录', 'D:\satori\空目录'])
    """
    但是该目录下必须有__init__.py文件,如果没有那么会打印_NamespacePath
    """
    
    
    # 我们在里面创建一个__init__.py文件
    with open("空目录/__init__.py", "w") as f:
        pass
    
    # 然后重新加载
    import importlib
    importlib.reload(空目录)
    # 成功显示
    print(空目录.__path__)  # ['D:\satori\空目录']
    
  • 相关阅读:
    python打印出当下的小时、分钟
    flask_ajax登录注册
    flask_SQlalchemy的复杂使用
    flask使用现有的数据表、在网页中显示数据
    js 的DOMdocument的使用
    pymysql的是使用
    通过ajax修改div id="div1" 的值
    关于django2.2使用xadmin的方法
    DOS windows 使用bat脚本获取 IP MAC 系统信息
    apache https 双向证书生成
  • 原文地址:https://www.cnblogs.com/traditional/p/11730906.html
Copyright © 2011-2022 走看看