楔子

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

__name__

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

  1. print(int.__name__) # int
  2. print(type.__name__) # type
  3. def foo(): pass
  4. print(foo.__name__) # foo
  5. class A:
  6. pass
  7. print(A.__name__) # A
  8. print(object.__name__) # object
  9. import sys
  10. print(sys.__name__) # sys
  11. import pandas as pd
  12. print(pd.__name__) # pandas

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

这里提一下__name__和__qualname__

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

  1. print(str.__name__) # str
  2. print(str.__qualname__) # str
  3. print(str.join.__name__) # join
  4. print(str.join.__qualname__) # str.join
  5. class A:
  6. class B:
  7. def foo(self):
  8. pass
  9. print(A.B.foo.__name__) # foo
  10. print(A.B.foo.__qualname__) # A.B.foo
  11. import tornado.web
  12. print(tornado.web.RedirectHandler.write.__name__) # write
  13. print(tornado.web.RedirectHandler.write.__qualname__) # RequestHandler.write

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

__doc__

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

  1. class A:
  2. """
  3. 这个是一个类
  4. 名叫class A
  5. """
  6. def __init__(self):
  7. """
  8. 这是构造函数
  9. """
  10. print(A.__doc__)
  11. """
  12. 这个是一个类
  13. 名叫class A
  14. """
  15. print(A.__init__.__doc__)
  16. """
  17. 这是构造函数
  18. """

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

__base__

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

  1. class A:
  2. pass
  3. class B(int, A):
  4. pass
  5. print(B.__base__) # <class 'int'>
  6. """
  7. 但是我们看到__base__只显示继承的类的其中一个
  8. 那么有没有办法全部显示呢?
  9. 答案是使用__bases__
  10. """
  11. print(B.__bases__) # (<class 'int'>, <class '__main__.A'>)
  12. print(A.__base__) # <class 'object'>
  13. print(A.__bases__) # (<class 'object'>,)
  14. """
  15. 我们看到,如果显式地继承了某个类,会打印继承的类的名字
  16. 如果没有,那么打印object
  17. """

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

__class__

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

  1. print("".__class__) # <class 'str'>
  2. print({}.__class__) # <class 'dict'>
  3. print([].__class__) # <class 'list'>
  4. print(int.__class__) # <class 'type'>
  5. print(object.__class__) # <class 'type'>
  6. print(type.__class__) # <class 'type'>

__module__

显示一个对象所在的模块

  1. print(str.__module__) # builtins
  2. from tornado.web import RedirectHandler
  3. print(RedirectHandler.__module__) # tornado.web
  4. import numpy
  5. print(numpy.ndarray.__module__) # numpy
  6. from numpy.core._multiarray_umath import ndarray
  7. print(ndarray.__module__) # numpy
  8. print(getattr.__module__) # builtins

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

__dict__

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

__file__

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

  1. import datetime
  2. print(datetime.__file__) # C:\python38\lib\datetime.py
  3. import tornado
  4. print(tornado.__file__) # C:\python38\lib\site-packages\tornado\__init__.py
  5. """
  6. 我们说对于单独的文件所构成的模块来讲,它的__file__就是其文件所在的绝对路径
  7. 如果是目录所构成的模块,那么__file__就是内部的__init__.py的绝对路径
  8. """
  9. from pandas import core
  10. print(core.__file__) # C:\python38\lib\site-packages\pandas\core\__init__.py
  11. # 这个时候问题来了,如果这个目录没有__init__.py文件怎么办?
  12. import 空目录
  13. print(空目录.__file__) # None
  14. # 如果没有的话,那么显示的为None

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

__path__

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

  1. from pandas import core
  2. print(core.__path__) # ['C:\\python38\\lib\\site-packages\\pandas\\core']
  3. import tornado
  4. print(tornado.__path__) # ['C:\\python38\\lib\\site-packages\\tornado']
  5. """
  6. 这里的__path__打印的是对应目录的绝对路径
  7. """
  8. import 空目录
  9. print(空目录.__path__) # _NamespacePath(['D:\\satori\\空目录', 'D:\\satori\\空目录'])
  10. """
  11. 但是该目录下必须有__init__.py文件,如果没有那么会打印_NamespacePath
  12. """
  13. # 我们在里面创建一个__init__.py文件
  14. with open("空目录/__init__.py", "w") as f:
  15. pass
  16. # 然后重新加载
  17. import importlib
  18. importlib.reload(空目录)
  19. # 成功显示
  20. print(空目录.__path__) # ['D:\\satori\\空目录']

详解python中的生成器表达式的更多相关文章

  1. 详解Python中的生成器表达式(generator expression)

    介绍 1.生成器表达式(generator expression)也叫生成器推导式或生成器解析式,用法与列表推导式非常相似,在形式上生成器推导式使用圆括号(parentheses)作为定界符,而不是列 ...

  2. 举例详解Python中的split()函数的使用方法

    这篇文章主要介绍了举例详解Python中的split()函数的使用方法,split()函数的使用是Python学习当中的基础知识,通常用于将字符串切片并转换为列表,需要的朋友可以参考下   函数:sp ...

  3. 详解Python中re.sub--转载

    [背景] Python中的正则表达式方面的功能,很强大. 其中就包括re.sub,实现正则的替换. 功能很强大,所以导致用法稍微有点复杂. 所以当遇到稍微复杂的用法时候,就容易犯错. 所以此处,总结一 ...

  4. 详解Python中内置的NotImplemented类型的用法

    它是什么? ? 1 2 >>> type(NotImplemented) <type 'NotImplementedType'> NotImplemented 是Pyth ...

  5. 详解Python中的循环语句的用法

    一.简介 Python的条件和循环语句,决定了程序的控制流程,体现结构的多样性.须重要理解,if.while.for以及与它们相搭配的 else. elif.break.continue和pass语句 ...

  6. 详解python中@的用法

    python中@的用法 @是一个装饰器,针对函数,起调用传参的作用. 有修饰和被修饰的区别,‘@function'作为一个装饰器,用来修饰紧跟着的函数(可以是另一个装饰器,也可以是函数定义). 代码1 ...

  7. Python Deque 模块使用详解,python中yield的用法详解

    Deque模块是Python标准库collections中的一项. 它提供了两端都可以操作的序列, 这意味着, 你可以在序列前后都执行添加或删除. https://blog.csdn.net/qq_3 ...

  8. 详解Python中的__init__和__new__(静态方法)

    一.__init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如: #-*- co ...

  9. 详解Python中的__new__、__init__、__call__三个特殊方法(zz)

    __new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪来的self)__init__ : 对象的初始化, 是一个实例方法,第一个参数是self ...

随机推荐

  1. Delphi ActionList详解

    一个友好的用户界面,必须具有下拉菜单,弹出菜单,工具条和快捷键.同样一个功能,程序员可能要提供几种操作方式,如文本拷贝,菜单命令&Copy,快捷键Ctrl+C,工具条上的拷贝按钮,都是程序员提 ...

  2. GitHub开源史上最大规模中文知识图谱

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/m0_38106923/article/d ...

  3. 线程回调,线程中的队列,事件,greenlet模块,gevent模块,自定义补丁, 单线程实现并发,协程

    1.线程回调 在线程池/进程池每次提交任务,都会返回一个表示任务的对象,Future对象Future对象具备一个绑定方法,add_done_callback 用于指定回调函数 add 意味着可以添加多 ...

  4. 【AMAD】django-oauth-toolkit -- 为Django集成Oauth2加入一些好货!

    简介 个人评分 简介 如果你面对下面其中的一个问题: 你的Django app需要暴露一个接口,你希望能够收到Oauth2协议的保护 你需要实现Oauth2鉴权服务器,让你的基础设施可以进行token ...

  5. kubespray 修改配置

    1.安装前的修改配置 # [root@slave1 kubespray]# vim inventory/local/group_vars/k8s-cluster.yml kube_network_pl ...

  6. sops的配置过程

    0.demo关键 1.关键信息,不能用5.1.6版本的,还有很多坑 蓝鲸版本: 标准运维:bk_sops_V3.1.39.tar 2.简单理解: 标准运维实际上调用作业平台job的API去执行 要跑通 ...

  7. Linux文件权限基础回顾介绍

    文件的权限 文件权限的概述: 权限贯穿运维的一生

  8. web/服务器知识

    一 PV 推到出 QPS 你想建设一个能承受500万PV/每天的网站吗? 500万PV是什么概念?服务器每秒要处理多少个请求才能应对?如果计算呢?? PV是什么:PV是page view的简写.PV是 ...

  9. 向量运算(lua,三维) 点乘、叉乘、模、夹角

    向量运算在游戏制作中经常用到,稍微总结一下. 一.点乘 如图,假设   向量a与b的点乘表示a在b上的投影与b的模的乘积 公式: 代码: function MathHelper.GetVector3D ...

  10. Bootstrap3基础教程 01 概述

    移动设备优先是 Bootstrap 3 的最显著的变化. 基础的页面: <!DOCTYPE html> <html> <head> <meta charset ...