前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python内置(2)异常、常量、globals

Python内置(2)异常、常量、globals

作者头像
一只大鸽子
发布2022-12-06 14:29:46
9120
发布2022-12-06 14:29:46
举报

异常

Python有66个内置的异常(exception)类,每个类都旨在供用户,标准库和其他所有人使用,作为解释和捕获代码中错误的有意义的方法。

为了确切解释为什么Python中有单独的异常类,这里有一个快速示例:

代码语言:javascript
复制
def fetch_from_cache(key):
    """Returns a key's value from cached items."""
    if key is None:
        raise ValueError('key must not be None')

    return cached_items[key]

def get_value(key):
    try:
        value = fetch_from_cache(key)
    except KeyError:
        value = fetch_from_api(key)

    return values

专注于函数get_value。如果key存在,它应该返回一个缓存值,否则从API获取数据。

该函数中可能发生 3 件事:

  • • 如果key不在缓存中,则尝试访问cached_items[key]将引发一个KeyError .这会在try块中捕获,并进行 API 调用以获取数据。
  • • 如果key存在于缓存中,则按原样返回。
  • • 还有第三种情况,其中keyNone

如果键是None ,则fetch_from_cache引发 一个ValueError ,指示提供给此函数的值不合适。由于该try块只捕获 KeyError,因此此错误直接显示给用户。

如果没有预定义ValueErrorKeyError,就不能这样区分错误类型。

关于异常的更多内容,如异常的子类化,Exception几乎是任何异常的父类、BaseException是所有异常的父类。这里不在赘述。

现在我应该指出,上面输出中的所有大写值都不是异常类型,实际上,Python中有另一种类型的内置对象是大写的:常量。让我们来谈谈这些。

常量

有5种内置的常量(constants):True, False, None, Ellipsis,和NotImplemented。

Ture, False 和 None 出现的很多。Ellipsis(省略号)很有意思,它有两种形式:Ellipsis...。最常出现在类型注解(annotations)和一些切片操作中。 NotImplemented用于类内的运算符(operator)定义,当你想要告诉Python类的运算符还没有具体定义。

Python中的对象可以通过实现__add__实现对+运算符的支持。__iadd__+=提供支持。等等。例如:

代码语言:javascript
复制
class MyNumber:
    def __add__(self, other):
        return other + 42
代码语言:javascript
复制
>>> num = MyNumber()
>>> num + 3
45
>>> num + 100
142

补充 右运算符。上面实现的__add__ 只有对象在运算符左侧才有效。 __radd__是右运算符,添加后就可以计算3+num

如果你想要只在整数进行加法,而不包括浮点数,这是就用到了NotImplemented

代码语言:javascript
复制
class MyNumber:
    def __add__(self, other):
        if isinstance(other, float):
            return NotImplemented

        return other + 42

关于常量的一个奇怪的事实是,它们甚至不是在Python中实现的,而是直接在C代码中实现的。

globals

内置的输出有一些奇怪的东西,例如__spec__,__loader____debug__等。

这些实际上不是builtins模块所独有的。这些属性都存在于Python中每个模块的全局范围内,因为它们是模块属性。它们保存有关导入所需的模块的信息。让我们来看看它们: __name__ 包含模块的名称。例如builtins.__name__的值是字符串'builtins'。当你运行一个Python文件,也是在运行一个模块,此时该模块的名称为__main__。这就结束了为什么 if __name__ == '__main__'内的语句会被执行。

__doc__ 包含模块的文档字符串。这是执行help(module_name)时显示为模块说明的内容。

__package__ 此模块所属的包。对于顶级模块,它与__name__相同。对于子模块,它是包的__name__ 。例如:

代码语言:javascript
复制
>>> import urllib.request
>>> urllib.__package__
'urllib'
>>> urllib.request.__name__
'urllib.request'
>>> urllib.request.__package__
'urllib'

__spec__ 这是指模块的空间。它包含元数据,例如模块名称,它是哪种模块,以及它的创建和加载方式。

__loader__ __loader__设置为导入在加载模块时使用的加载程序对象。这个特定的模块在_frozen_importlib模块中定义,并且是用于导入内置模块的内容。

__import__ __import__是定义import语句在 Python 中的工作方式的内置函数。

代码语言:javascript
复制
np = __import__('numpy')  # Same as doing 'import numpy as np'

__debug__ 这是 Python 中的一个全局常量值,几乎总是设置为 True。它指的是Python在调试模式下运行。默认情况下,Python始终在调试模式下运行。

此外,__debug__, True, FalseNone是 Python 中唯一的真常量,即这 4 个是 Python 中唯一不能用新值覆盖的全局变量。

__build_class__ 此全局变量是在 Python 3.1 中添加的,以允许类定义接受任意位置和关键字参数。为什么这是一个功能有很长的技术原因,它涉及元类等高级主题,所以不幸的是,我不会解释为什么它存在。

__cached__ 导入__cached__模块时,该属性存储该模块的已编译 Python 字节码的缓存文件的路径。你可能会惊讶,Python也要编译吗?是的。Python被编译。事实上,所有的Python代码都是被编译的,但不是机器代码 ,而是字节码(bytecode)。让我通过解释Python如何运行你的代码来解释这一点。

  1. 1. 获取源文件,并解析为语法树。保证语法正确。
  2. 2. 将语法树编译为字节码。字节码是Python虚拟机(virtual machine,VM)的一组微指令。这个“虚拟机”是Python的解释器逻辑所在的位置。它本质上是在您的机器上模拟一个非常简单的基于堆栈的计算机,以便执行您编写的Python代码。
  3. 3. 然后,在 Python VM 上运行此代码形式的代码。字节码指令很简单,例如从当前堆栈中推送和弹出数据。当这些指令一个接一个地运行时,这些指令中的每一个都会执行整个程序。

现在,由于上面的“编译为字节码”步骤在导入模块时需要花费大量时间,因此Python将字节码存储(编组)到.pyc文件中,并将其存储在名为__pycache__的文件夹中。然后,导入模块的__cached__参数指向此.pyc文件。你可以直接在Python代码中运行或导入一个.pyc文件,就像运行一个.py文件。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-09-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一只大鸽子 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 异常
  • 常量
  • globals
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档