语法最佳实践–类级别以下
- 列表推导(list comprehension)。
- 迭代器(iterator)和生成器(generator)。
- 描述符(descriptor)和属性(property)。
- 装饰器(decorator)。
- with 和 contextlib。
Python 的内置类型
- 字符串与字节
- Python 3 中只有一种能够保存文本信息的数据类型,就是 str(string,字符串)。是不可变的序列,保存的是 Unicode 码位(code point)。
- Python 3 中用 bytes 对象处理字节字符串。
- 从 Python 3.0 开始,所有没有前缀的字符串都是 Unicode。因此,所有用单引号(’)、双引号(")或成组的3个引号(单引号或双引号)包围且没有前缀的值都表示 str 数据类型。
- 在 Python 2 中,Unicode 需要有 u 前缀。从 Python 3.3 开始,为保证向后兼容,仍然可以使用这个前缀,但它在 Python 3 中没有任何语法上的意义。
- 将字符串对象编码为字节序列的方法有两种:
- 利用 str.encode(encoding, errors)方法,用注册编解码器(registeredcodec)对字符串进行编码。编解码器由 encoding 参数指定,默认值为’utf-8’。
- 利用 bytes(source, encoding, errors)构造函数,创建一个新的字节序列。如果source是str类型,那么必须指定 encoding 参数,它没有默认值。
- 类似方法可以将 bytes 表示的二进制数据转换成字符串:
- 利用 bytes.decode(encoding, errors)方法,用注册编解码器对字节进行解码。参数含义及其默认值与 str.encode()相同。
- 利用 str(source, encoding, error)构造函数,创建一个新的字符串实例。与 bytes()构造函数用法类似,如果 source 是字节序列的话,必须指定 str 函数的 encoding 参数,它没有默认值。
- 集合类型。
- 列表与元组。
- 列表是动态的,其大小可以改变;而元组是不可变的,一旦创建就不能修改。
- Python 中的列表是由对其他对象的引用组成的的连续数组。指向这个数组的指针及其长度被保存在一个列表头结构中。这意味着,每次添加或删除一个元素时,由引用组成的数组需要改变大小(重新分配)。Python 在创建这些数组时采用了指数过分配(exponential over-allocation),所以并不是每次操作都需要改变数组大小。
- Python 在内置的 collections 模块中提供了 deque(双端队列)。
- 列表推导更加高效之外,也更加简短,涉及的语法元素也更少。在大型程序中,这意味着更少的错误,代码也更容易阅读和理解。
- 使用 enumerate(枚举),在循环中使用序列时,这个内置函数可以很方便地获取其索引。
- 合并多个列表(或任意可迭代对象)中的元素,那么可以使用内置的 zip()函数。对 zip()函数返回的结果再次调用 zip(),可以将其恢复原状。
- 序列解包(sequence unpacking),这种方法并不限于列表和元组,而是适用于任意序列类型(甚至包括字符串和字节序列)。
- 解包还可以利用带星号的表达式获取单个变量中的多个元素,只要它的解释没有歧义即可。还可以对嵌套序列进行解包。
- 字典。
- Python 3 的字典的keys()、values()和items() 3个方法的返回值类型不再是列表。现在 keys()、values()和 items() 返回的是视图对象(viewobjects)。
- keys():返回 dict_keys对象,可以查看字典的所有键。
- values():返回 dict_values对象,可以查看字典的所有值。
- items():返回 dict_items对象,可以查看字典所有的(key, value)二元元组。
- 视图对象可以动态查看字典的内容,因此每次字典发生变化时,视图都会相应改变。
- CPython 使用伪随机探测(pseudo-random probing)的散列表(hash table)作为字典的底层数据结构。
- 字典的 3 个基本操作(添加元素、获取元素和删除元素)的平均时间复杂度为 O(1)。
- 在复制和遍历字典的操作中,最坏情况复杂度中的 n 是字典曾经达到的最大元素数目,而不是当前元素数目。
- 使用字典的常见陷阱之一,就是它并不会按照键的添加顺序来保存元素的顺序。
- Python 标准库的 collections 模块提供了名为 OrderedDict 的有序字典。OrderedDict 还有一些其他功能,例如利用 popitem() 方法在双端取出元素或者利用 move_to_end() 方法将指定元素移动到某一端。
- Python 3 的字典的keys()、values()和items() 3个方法的返回值类型不再是列表。现在 keys()、values()和 items() 返回的是视图对象(viewobjects)。
- 集合。
- set():一种可变的、无序的、有限的集合,其元素是唯一的、不可变的(可哈希的)对象。
- frozenset():一种不可变的、可哈希的、无序的集合,其元素是唯一的、不可变的(可哈希的)对象。
- 由于 frozenset() 具有不变性,它可以用作字典的键,也可以作为其他 set() 和 frozenset() 的元素。
- 创建可变集合方法有以下 3 种:
- 调用set(),选择性地接受可迭代对象作为初始化参数,例如set([0, 1, 2])。
- 使用集合推导,例如 {element for element in range(3)}。
- 使用集合字面值,例如 {1, 2, 3}。
- 空的花括号 {} 表示的是空的字典字面值。
- 超越基础集合类型——collections 模块。
- namedtuple():用于创建元组子类的工厂函数(factory function),可以通过属性名来访问它的元索引。
- deque:双端队列,类似列表,是栈和队列的一般化,可以在两端快速添加或取出元素。
- ChainMap:类似字典的类,用于创建多个映射的单一视图。
- Counter:字典子类,由于对可哈希对象进行计数。
- OrderedDict:字典子类,可以保存元素的添加顺序。
- defaultdict:字典子类,可以通过调用用户自定义的工厂函数来设置缺失值。
- 列表与元组。
- 高级语法。
- 迭代器(iterator)。
- 迭代器只不过是一个实现了迭代器协议的容器对象。它基于以下两个方法。
__next__
:返回容器的下一个元素。__iter__
:返回迭代器本身。
- 迭代器只不过是一个实现了迭代器协议的容器对象。它基于以下两个方法。
- 生成器(generator)。
- 基于 yield 语句,生成器可以暂停函数并返回一个中间结果。该函数会保存执行上下文,稍后在必要时可以恢复。
- 生成器是 Python 中协程、异步并发等其他概念的基础。
- 装饰器(decorator)。
- Python 装饰器的作用是使函数包装与方法包装(一个函数,接受函数并返回其增强函数)变得更容易阅读和理解。最初的使用场景是在方法定义的开头能够将其定义为类方法或静态方法。
- 装饰器通常是一个命名的对象(不允许使用 lambda 表达式),在被(装饰函数)调用时接受单一参数,并返回另一个可调用对象。
- 装饰器语法只是语法糖而已。
- 实现:函数、类、参数化装饰器、保存內省的装饰器。
- 任何情况下,装饰器在处理API时,一个好的做法是将它们聚集在一个易于维护的模块中。
- 常见的装饰器模式:参数检查、缓存、代理、上下文提供者。
- 上下文管理器(context manager)。
- 确保即使在出现错误的情况下也能运行某些清理代码。
- 使用场景:关闭一个文件、释放一个锁、创建一个临时的代码补丁、在特殊环境中运行受保护的代码。
- 实现:类、函数–contextlib 模块。
- 迭代器(iterator)。
- 其他语法元素
- for…else… 语句
- 函数注解:Python 3 最独特的功能之一。没有任何语法上的意义。官方文档解释:函数注解是关于用户自定义函数使用的类型的完全可选的元信息。