ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python 2 遗留语法速成指南:learnxinyminutes-docs 仓库 hu/pythonlegacy.md 深度解析

Python 2 遗留语法速成指南:learnxinyminutes-docs 仓库 hu/pythonlegacy.md 深度解析 文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载本文围绕 learnxinyminutes-docs 仓库中的 hu/pythonlegacy.md匈牙利语版 Python 2 速成教程展开完整还原其全部代码示例与知识脉络并结合仓库源码说明该文档的组织方式、frontmatter 校验规则与 Python 3 教程的互补关系。读完本文你将系统掌握 Python 2.7 的核心语法——从数据类型、集合、控制流、函数、类到模块、生成器与装饰器并了解这份可执行的伪代码式教程在仓库中的定位与用法。文档背景仓库中的 Python 2 速成教程learnxinyminutes-docs 是一个以可运行的、带注释的代码形式呈现编程语言速成教程的开源仓库见 README.md。仓库中每一种语言教程都对应一个 Markdown 文件正文是一整段可以直接运行的代码脚本代码行间用注释讲解知识点。本文关联文档 hu/pythonlegacy.md 是该教程的匈牙利语译本其源头是仓库根目录的英文原版 pythonlegacy.md。英文原版的 YAML frontmatter 中标明了文档身份name: Python 2 (legacy) contributors: - [Louie Dinh, http://ldinh.ca] - ... filename: learnpythonlegacy.py其中filename: learnpythonlegacy.py揭示了这份文档的独特设计整篇教程就是一份语法合法、可直接运行的 Python 2 脚本所有知识点都以# 结果的注释形式给出即时验证。匈牙利语译本则保留了同样的代码骨架将全部注释翻译为匈牙利语并在 frontmatter 中通过translators字段记录译者信息如 Tamás Diószegi。仓库的 lint 工具链为这类文档提供了质量保障lint/frontmatter.py 会解析每个 Markdown 文件的 YAML frontmatter并校验允许的键name、where_x_eq_name、category、filename、contributors、translators及其类型——contributors/translators必须是[姓名, 链接]形式的列表lint/encoding.sh 检查所有.md文件必须是 UTF-8 或 US-ASCII 编码且不含 UTF-8 BOM。在文档定位上hu/pythonlegacy.md 明确声明本教程面向 Python 2.7 及 2.x 系列而 Python 2.7 的生命周期已于 2020 年结束因此初学者更推荐从 Python 3 教程仓库根目录python.md即 zh-cn/python.md 等译本的蓝本开始。仓库内多语言 Python 3 教程如 zh-cn/python.md也通过想学旧版 Python 2请参考 pythonlegacy 教程的指引与本文档互相呼应。此外文档还提到借助 Python 的 [__future__imports] 机制可以写出同时兼容 2.7 与 3.x 的代码此时同样建议以 Python 3 教程为准。下面按原文档的七个章节逐节还原并深入讲解全部代码。一、基本数据类型与运算符注释、数字与基础运算# 单行注释以井号开头 多行字符串可以用三个 括起来书写 经常被用作多行注释 # 可以使用数字 3 # 3 # 基本运算与预期一致 1 1 # 2 8 - 1 # 7 10 * 2 # 20 35 / 5 # 7除法Python 2 最容易踩的坑Python 2 中/对整数执行的是向下取整的整数除法这是与 Python 3 最显著的差异之一5 / 2 # 2 # 要修正除法需要使用 float浮点类型 2.0 # 这是一个 float 11.0 / 4.0 # 2.75 好多了 # 整数除法的结果对正数和负数都向下取整 5 // 3 # 1 5.0 // 3.0 # 1.0 对 float 也适用 -5 // 3 # -2 -5.0 // 3.0 # -2.0 # 也可以导入 division 模块参见第 6 节模块 # 这样只用 / 就能做精确除法 from __future__ import division 11 / 4 # 2.75 普通除法 11 // 4 # 2 向下取整除法注意两点//地板除在正负数上都向负无穷取整-5 // 3得-2而非-1而通过from __future__ import division可以把/的行为切换到真除法这正是文档开头提到的、让代码同时兼容 2.7 与 3.x 的__future__机制的一个典型实例。取模、幂与优先级# 取模运算 7 % 3 # 1 # 幂运算x 的 y 次方 2 ** 4 # 16 # 用括号控制优先级 (1 3) * 2 # 8布尔运算与真值判定# 布尔运算符 # 注意and 和 or 只能用小写 True and False # False False or True # True # 布尔运算符也可以用在整数上 0 and 2 # 0 -5 or 0 # -5 0 False # True 2 True # False 1 True # True # 用 not 关键字取反 not True # False not False # True # 相等性判断 1 1 # True 2 1 # False # 不等性判断 ! 1 ! 1 # False 2 ! 1 # True # 更多比较 1 10 # True 1 10 # False 2 2 # True 2 2 # True # 比较可以链式书写 1 2 3 # True 2 3 2 # FalsePython 中任何对象都可以用于布尔上下文文档给出了完整的falsey 值清单None任何数值类型的 0如0、0L、0.0、0j空序列如、()、[]空容器如{}、set()按特定规则判定的某些用户自定义类实例参见对象模型中的__nonzero__约定其余一切值都是 truthybool(0) # False bool() # False这也是0 and 2返回0、-5 or 0返回-5的原因——and/or返回的是实际参与运算的操作数而非单纯的布尔值。字符串拼接、索引、格式化# 字符串可以用 或 括起来 这是一个字符串。 这是另一个字符串。 # 字符串可以相加 Hello world! # Hello world! # 不加 也可以拼接 Hello world! # Hello world! # ……也可以相乘 Hello * 3 # HelloHelloHello # 可以把字符串当作字符列表来索引 This is a string[0] # T # len 函数返回字符串长度 len(This is a string) # 16 # 字符串格式化可以用 % 符号 # 从 Python 3.1 起 % 已被标记为弃用将来会被移除但了解一下它的工作原理仍然有用 x alma # 苹果 y citrom # 柠檬 z 篮子里的元素%s 和 %s % (x, y) # 字符串格式化的新方式是使用 format 方法目前推荐使用 {} 是一个 {} 文本.format(这, 占位符) A {0} 和 {1}.format(字符串, 可格式化) # 如果不想数位置可以给位置命名 {name} 最爱 {food}.format(nameBob, foodlasagna)None 与 is 运算符# None 是一个对象 None # None # 与 None 比较不要用 应该用 is 关键字 etc is None # False None is None # True # is 运算符判断对象是否同一。 # 对原始类型来说用处不大但对对象来说很有用。is比较的是对象身份内存地址是否相同比较的是值是否相等。对可变对象而言二者语义差别显著这是后续类与对象章节的重要前提。二、变量与集合输入、变量与三元表达式# 存在一个 print 语句Python 2 中 print 是语句而非函数 print Im Python. Nice to meet you! # Im Python. Nice to meet you! # 可以这样简单地从控制台请求输入 input_string_var raw_input(Enter some data: ) # 返回输入的字符串 input_var input(Enter some data: ) # 将输入作为 Python 代码求值 # 注意正因为上述原因input() 方法要谨慎使用 # 备注在 Python 3 中 input() 已弃用raw_input() 被改名为 input() # 变量在使用前不需要声明 some_var 5 # 按惯例使用小写字母加下划线命名 some_var # 5 # 引用未赋值的变量会抛出错误参见控制流一节的异常处理 some_other_var # 抛出 NameError # if 可以用作表达式等价于 C 语言的 ?: 三元运算符 yahoo! if 3 2 else 2 # yahoo!这里raw_input()与input()的区别是关键安全点input()会把用户输入当作 Python 代码求值存在安全隐患Python 3 中已彻底移除该行为并将raw_input()改名为input()。列表增删改查与切片# 列表可以存放序列 li [] # 也可以在初始化时就给出元素 other_li [4, 5, 6] # append 方法在列表末尾追加新元素 li.append(1) # li 现在是 [1] li.append(2) # li 现在是 [1, 2] li.append(4) # li 现在是 [1, 2, 4] li.append(3) # li 现在是 [1, 2, 4, 3] # pop 方法从末尾移除元素 li.pop() # 3li 现在是 [1, 2, 4] # 再放回去 li.append(3) # li 又是 [1, 2, 4, 3] # 列表元素用数组下标访问 li[0] # 1 # 已初始化的值可以用 赋予新值 li[0] 42 li[0] # 42 li[0] 1 # 恢复原值 # 这样访问最后一个元素 li[-1] # 3 # 越界访问会抛出 IndexError li[4] # 抛出 IndexError # 列表片段用切片slice语法切出数学上是一个左闭右开区间 li[1:3] # [2, 4] # 可以省略开头 li[2:] # [4, 3] # 可以省略结尾 li[:3] # [1, 2, 4] # 每两个元素取一个 li[::2] # [1, 4] # 列表的副本逆序排列 li[::-1] # [3, 4, 2, 1] # 上述组合可以构成更复杂的切片指令 li[start:end:step]切片语法的通用形式是li[start:end:step]li[1:3]取下标 1、2 两个元素右端点不包含li[::-1]用步长-1实现逆序副本越界下标则抛出IndexError。切片操作每次都会生成新列表不会改动原列表。# 列表元素用 del 命令删除 del li[2] # li 现在是 [1, 2, 3] # 列表可以相加 li other_li # [1, 2, 3, 4, 5, 6] # 注意原来的 li 和 other_li 值不变 # 用 extend() 可以拼接 li.extend(other_li) # li 现在是 [1, 2, 3, 4, 5, 6] # 移除某个元素的第一次出现 li.remove(2) # li 现在是 [1, 3, 4, 5, 6] li.remove(2) # 抛出 ValueError因为 2 已不在列表中 # 在任意位置插入元素 li.insert(1, 2) # li 又是 [1, 2, 3, 4, 5, 6] # 查找某元素第一次出现的位置 li.index(2) # 1 li.index(7) # 抛出 ValueError因为 7 不在列表中 # 用 in 检查元素是否在列表中 1 in li # True # len() 返回列表长度 len(li) # 6注意生成新列表与extend()原地修改的本质区别前者返回新对象后者就地扩展并返回None。remove()在元素不存在时抛出ValueErrorindex()同理。元组不可变序列与解包# 元组tuple类似列表但不可修改 tup (1, 2, 3) tup[0] # 1 tup[0] 3 # 抛出 TypeError # 所有列表操作对元组同样适用 len(tup) # 3 tup (4, 5, 6) # (1, 2, 3, 4, 5, 6) tup[:2] # (1, 2) 2 in tup # True # 元组和列表可以解包到不同变量中 a, b, c (1, 2, 3) # 这样 a 是 1b 是 2c 是 3 d, e, f 4, 5, 6 # 括号可以省略 # 省略括号时默认生成元组 g 4, 5, 6 # (4, 5, 6) # 看交换两个值多简单 e, d d, e # d 现在是 5e 现在是 4元组的关键特性是不可变性tup[0] 3抛TypeError这使它可以作为字典的键。解包unpacking与交换两个值e, d d, e则是元组在 Python 2 中最高频的实用技巧。字典键值对的增删查改# 字典dictionary存放键值对 empty_dict {} # 这个直接带值初始化 filled_dict {one: 1, two: 2, three: 3} # 字典的值用 [] 下标访问 filled_dict[one] # 1 # keys() 方法返回键的列表 filled_dict.keys() # [three, two, one] # 注意字典键值对的顺序不保证 # 上面的例子中你拿到的顺序可能不同 # values() 方法取出值的列表 filled_dict.values() # [3, 2, 1] # 参见上面的顺序说明 # items() 方法返回所有键值对作为元组列表 filled_dict.items() # [(one, 1), (two, 2), (three, 3)] # 用 in 关键字检查键是否存在于字典中 one in filled_dict # True 1 in filled_dict # False # 访问不存在的键会抛出 KeyError filled_dict[four] # KeyError # 用 get() 方法可以避免 KeyError filled_dict.get(one) # 1 filled_dict.get(four) # None # 可以给 get() 指定缺省返回值用于键缺失的情况 filled_dict.get(one, 4) # 1 filled_dict.get(four, 4) # 4 # 注意filled_dict.get(four) 仍然是 None # 即 get 不会把默认值写回字典 # 键值可以用类似列表的语法赋值 filled_dict[four] 4 # 之后 filled_dict[four] 4 # setdefault() 只在键还没有值时才设置 filled_dict.setdefault(five, 5) # filled_dict[five] 被设为 5 filled_dict.setdefault(five, 6) # filled_dict[five] 仍然是 5Python 2 的字典是无序的因此keys()/values()/items()的返回顺序不保证。get(key, default)与setdefault(key, value)是避免KeyError的两个常用手段且get不会修改字典setdefault只在键缺失时才写入。集合去重与集合运算# 集合set像一个列表但每个元素只能出现一次 empty_set set() # 用几个元素初始化 some_set set([1, 2, 2, 3, 4]) # some_set 现在是 set([1, 2, 3, 4]) # 顺序同样不保证即使有时看起来是有序的 another_set set([4, 3, 2, 2, 1]) # another_set 现在是 set([1, 2, 3, 4]) # 从 Python 2.7 起也可以用 {} 定义集合 filled_set {1, 2, 2, 3, 4} # {1, 2, 3, 4} # 添加新元素 filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5} # 用 运算符求交集 other_set {3, 4, 5, 6} filled_set other_set # {3, 4, 5} # 用 | 运算符求并集 filled_set | other_set # {1, 2, 3, 4, 5, 6} # 用 - 求差集 {1, 2, 3, 4} - {2, 3, 5} # {1, 4} # 用 ^ 求对称差 {1, 2, 3, 4} ^ {2, 3, 5} # {1, 4, 5} # 检查左侧集合是否包含右侧集合 {1, 2} {1, 2, 3} # False # 检查左侧集合是否是右侧集合的子集 {1, 2} {1, 2, 3} # True # 用 in 检查集合成员 2 in filled_set # True 10 in filled_set # False集合自动去重set([1, 2, 2, 3, 4])得到{1, 2, 3, 4}。Python 2.7 新增了{}字面量集合语法且支持完整的集合运算交集、并集|、差集-、对称差^以及/表示的包含关系与子集判断。三、控制流条件分支与缩进# 先定义一个变量 some_var 5 # 这是 if 分支。缩进在语言中有实际意义 # 这段代码会输出some_var 小于 10 if some_var 10: print some_var 大于 10。 elif some_var 10: # elif 在 if 结构中是可选的 print some_var 小于 10。 else: # 这也是可选的 print some_var 正好是 10。Python 用缩进而非花括号表达代码块层次这是该语言的核心设计之一。for、range 与 while for 循环可以遍历列表 输出 狗是哺乳动物 猫是哺乳动物 老鼠是哺乳动物 for animal in [kutya, macska, eger]: # 狗、猫、老鼠 # 用 {0} 格式化字符串参见前面的说明 print A(z) {0} emlős.format(animal) # {0} 是哺乳动物 range(number) 返回从 0 到 number 的数字列表 输出 0 1 2 3 for i in range(4): print i range(lower, upper) 返回 lower 和 upper 之间的数字 输出 4 5 6 7 for i in range(4, 8): print i while 循环一直运行到条件为假 输出 0 1 2 3 x 0 while x 4: print x x 1 # x x 1 的简写range(n)生成0到n-1的列表range(lower, upper)生成[lower, upper)区间同样左闭右开。x 1是复合赋值运算符的简写。关于range与xrange的差异将在第 7 节结合生成器详细展开。异常处理与资源管理# 异常用 try/except 块处理 # Python 2.6 及以上 try: # 用 raise 抛出错误 raise IndexError(这是一个索引错误) except IndexError as e: pass # pass 是空占位操作这里可以调用错误处理代码 except (TypeError, NameError): pass # 需要时可以同时处理多种错误类型 else: # 在 except 块之后可选 print 一切正常 # 仅当上面没有错误时执行 finally: # 无论如何都会执行 print 这里可以释放资源等 # 释放资源可以用 with 代替 try/finally with open(myfile.txt) as f: for line in f: print linetry/except/else/finally四段式语义except捕获异常可用元组同时捕获多种类型Python 2.6 支持as e语法else仅在未发生异常时执行finally无条件执行。而with open(...) as f则自动管理文件句柄的打开与关闭是比手写try/finally更简洁的资源管理方式。四、函数定义、调用与参数传递# 用 def 关键字创建新函数 def add(x, y): print x 是 {0}y 是 {1}.format(x, y) return x y # 用 return 返回值 # 这样带参数调用函数 add(5, 6) # 控制台输出 x is 5 and y is 6返回值是 11 # 也可以用命名参数keyword arguments调用 add(y6, x5) # 这种情况下参数顺序无所谓可变参数*args 与 **kwargs# 可以定义接收可变数量参数的函数。 # 用 * 时参数会作为一个元组接收。 def varargs(*args): return args varargs(1, 2, 3) # (1, 2, 3) # 也可以定义接收可变数量命名参数的函数 # 用 ** 时参数会作为一个字典接收。 def keyword_args(**kwargs): return kwargs # 看看会发生什么 keyword_args(bigfoot, lochness) # {big: foot, loch: ness} # 两种方式可以同时使用 def all_the_args(*args, **kwargs): print args print kwargs all_the_args(1, 2, a3, b4) 的输出 (1, 2) {a: 3, b: 4} # 调用函数时可以使用上述 args 和 kwargs 的逆操作 # * 把一个列表展开成单独的参数** 把一个字典展开成命名参数。 args (1, 2, 3, 4) kwargs {a: 3, b: 4} all_the_args(*args) # 等价于 foo(1, 2, 3, 4) all_the_args(**kwargs) # 等价于 foo(a3, b4) all_the_args(*args, **kwargs) # 等价于 foo(1, 2, 3, 4, a3, b4) # 上述 args 和 kwargs 参数可以通过 * 和 ** 操作符再传给其他函数 def pass_all_the_args(*args, **kwargs): all_the_args(*args, **kwargs) print varargs(*args) print keyword_args(**kwargs)*args收集多余的位置参数为元组**kwargs收集多余的命名参数为字典。调用侧的*/**展开是与定义侧相反的操作二者配合可以写出极具通用性的包装函数。作用域与 global# 函数作用域 x 5 def set_x(num): # 局部变量 x 与全局变量 x 不是同一个 x num # 43 print x # 43 def set_global_x(num): global x print x # 5 x num # 把全局 x 设为 6 print x # 6 set_x(43) set_global_x(6)函数内赋值默认创建局部变量只有用global声明后函数内对变量的赋值才会作用于模块级全局变量。一等函数、lambda 与高阶函数# Python 中函数是一等first class类型 def create_adder(x): def adder(y): return x y return adder add_10 create_adder(10) add_10(3) # 13 # 也可以定义匿名函数 (lambda x: x 2)(3) # True (lambda x, y: x ** 2 y ** 2)(2, 1) # 5 # 存在内置的高阶函数 map(add_10, [1, 2, 3]) # [11, 12, 13] map(max, [1, 2, 3], [4, 2, 1]) # [4, 2, 3] filter(lambda x: x 5, [3, 4, 5, 6, 7]) # [6, 7] # 列表推导式list comprehensions可以很好地替代 map 和 filter [add_10(i) for i in [1, 2, 3]] # [11, 12, 13] [x for x in [3, 4, 5, 6, 7] if x 5] # [6, 7] # 也存在集合和字典推导式 {x for x in abcddeef if x in abc} # {a, b, c} {x: x ** 2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}闭包create_adder返回内部函数并捕获外层x、匿名函数lambda、内置高阶函数map/filter以及集合/字典推导式共同构成了 Python 2 函数式编程的基本工具集。其中列表推导式[表达式 for 元素 in 序列 if 条件]比map/filter更直观是 Python 社区的首选写法。五、类类定义、构造器与实例方法# 我们创建 object 类的子类 class Human(object): # 类级字段对类的所有实例都相同 species H. sapiens # 这个函数在类实例化时被调用。 # 注意名字前后双下划线是 Python 预定义对象和字段 # 语言内部使用但用户也可见的命名惯例。 # 不要发明新的、使用这种命名方式的名称 def __init__(self, name): # 把参数赋给实例的 name 属性 self.name name # 初始化一个字段 self.age 0 # 实例方法。每个方法的第一个参数都是 self即实例本身 def say(self, msg): return {0}: {1}.format(self.name, msg) # 类方法在类的所有实例间共享。 # 调用时第一个参数总是调用它的那个类。 classmethod def get_species(cls): return cls.species # 静态方法调用时不需要类引用或实例引用 staticmethod def grunt(): return *grunt*__init__是构造器双下划线命名是 Python 的魔法方法惯例self是实例方法约定俗成的第一个参数。classmethod的第一个参数是类本身clsstaticmethod则与类和实例都无关。property 与属性控制# property 标记的函数就像一个 getter。 # 使用它之后age 字段变成只读属性。 property def age(self): return self._age # 这样可以为字段定义 setter age.setter def age(self, age): self._age age # 这样允许删除字段 age.deleter def age(self): del self._ageproperty把方法变成属性访问器内部存储用带下划线的_age对外则通过age属性统一拦截读取、赋值与删除分别对应property、age.setter、age.deleter。实例化与行为验证# 实例化这个类 i Human(nameIan) print i.say(hi) # 输出Ian: hi j Human(Joel) print j.say(hello) # 输出Joel: hello # 调用类方法 i.get_species() # H. sapiens # 修改类级属性 Human.species H. neanderthalensis i.get_species() # H. neanderthalensis j.get_species() # H. neanderthalensis # 调用静态方法 Human.grunt() # *grunt* # 给字段赋新值 i.age 42 # 取字段的值 i.age # 42 # 删除字段 del i.age i.age # 抛出 AttributeError类级属性species被所有实例共享一旦通过类名修改所有实例的get_species()结果都会同步变化。而实例属性self.name、self.age各自独立。删除属性后访问会抛出AttributeError。六、模块# 这样导入模块 import math print math.sqrt(16) # 4.0 # 可以只从模块中导入某些函数 from math import ceil, floor print ceil(3.7) # 4.0 print floor(3.7) # 3.0 # 也可以导入一个模块的所有函数 # 注意不推荐这样做。 from math import * # 模块名可以缩短 import math as m math.sqrt(16) m.sqrt(16) # True # 可以确认这些函数确实是同一个 from math import sqrt math.sqrt m.sqrt sqrt # True # Python 模块就是简单的文件。 # 你可以编写自己的模块并导入它。 # 模块名与包含它的文件名相同。 # 这样查看一个模块定义了哪些字段和函数。 import math dir(math) # 如果当前运行的脚本所在目录中有一个 math.py 脚本 # 它会被加载而不是内置的 Python math 模块。 # 本地目录优先于内置库。模块导入的四种形态import math命名空间限定、from math import ceil, floor选择性导入、from math import *通配导入会污染命名空间不推荐、import math as m别名。dir(math)可以列出模块的全部成员。需要特别警惕的是当前目录下的同名.py文件会遮蔽内置模块——如果工作目录里存在math.pyimport math加载的将是它而非标准库这是 Python 模块解析顺序本地目录优先的经典陷阱。七、进阶生成器与装饰器生成器按需产生值# 生成器generator # 生成器在被请求时才生成值而不是预先存储它们。 # 下面的方法这还不是生成器把传入的 iterable 的元素翻倍 # 并存储它们。对于很大的 iterable这会占用大量空间 def double_numbers(iterable): double_arr [] for i in iterable: double_arr.append(i i) return double_arr # 运行下面的代码时我们会计算出所有数字的两倍 # 并把这个大列表返回给循环控制。 for value in double_numbers(range(1000000)): # test_non_generator print value if value 5: break # 不如改用生成器它在被请求时才生成下一个元素 def double_numbers_generator(iterable): for i in iterable: yield i i # 下面的代码每次只生成下一个数字然后进行逻辑判断。 # 这样当值超过 5 的界限时我们就中断循环 # 对列表中的大部分数字省去了翻倍运算这样快得多。 for value in double_numbers_generator(xrange(1000000)): # test_generator print value if value 5: break # 注意到 test_non_generator 用的是 range # 而 test_generator 用的是 xrange 吗 # 就像 double_numbers_generator 是 double_numbers 的生成器版本一样 # xrange 是 range 的生成器版本 # 它只在被请求时才生成下一个数字——本例中是在循环的下一次迭代时。普通函数用return一次性返回完整列表百万级元素时内存开销巨大生成器函数用yield逐次产出值调用方每迭代一次才计算下一个值。配合xrangerange的惰性版本Python 2 特有遍历前几项即可break时能省去对绝大部分元素的重复计算——这正是文档中这样快得多的底层原因。# 与列表推导式类似也可以使用生成器推导式generator comprehensions。 values (-x for x in [1, 2, 3, 4, 5]) for x in values: print(x) # 输出-1 -2 -3 -4 -5 # 也可以把生成器生成的所有元素作为列表取出 values (-x for x in [1, 2, 3, 4, 5]) gen_to_list list(values) print(gen_to_list) # [-1, -2, -3, -4, -5]生成器推导式用圆括号包裹与列表推导式的区别在于它不立即求值用list()可以一次性物化生成器的全部输出。装饰器包裹与增强函数# 装饰器decorator # 装饰器是高阶函数输入和输出都是函数。 # 下面这个简单例子中add_apples 装饰器把 Apple 元素 # 插入到被装饰的 get_fruits 函数的输出中。 def add_apples(func): def get_fruits(): fruits func() fruits.append(Apple) return fruits return get_fruits add_apples def get_fruits(): return [Banana, Mango, Orange] # 输出包含 Apple 元素 # Banana, Mango, Orange, Apple print , .join(get_fruits()) # 这个例子中我们给 say 函数加上 beg 装饰器。 # beg 调用 say。如果 say_please 参数为真 # 就修改结果语句。 from functools import wraps def beg(target_function): wraps(target_function) def wrapper(*args, **kwargs): msg, say_please target_function(*args, **kwargs) if say_please: return {} {}.format(msg, Please! I am poor :() return msg return wrapper beg def say(say_pleaseFalse): msg Can you buy me a beer? return msg, say_please print say() # Can you buy me a beer? print say(say_pleaseTrue) # Can you buy me a beer? Please! I am poor :(装饰器add_apples等价于get_fruits add_apples(get_fruits)它接收一个函数、返回增强后的新函数。第二个例子结合了*args/**kwargs透传与functools.wraps保留原函数的元信息演示了如何编写带参数判断的通用装饰器——这是 Python 2 中日志、鉴权、缓存等横切逻辑的标准实现模式。文档中的扩展学习资源原文档末尾附有还想了解更多的资源清单包含两类扩展材料原文以链接形式给出此处仅列出名称在线免费内容有Automate the Boring Stuff with Python、Learn Python The Hard Way、Dive Into Python、官方 Python 2 文档、Hitchhikers Guide to Python、Python Module of the Week、A Crash Course in Python for Scientists、First Steps With Python、LearnPython、Fullstack Python书籍则有Programming Python、Dive Into Python与Python Essential Reference。结语如何在本仓库继续学习本仓库以带注释的可执行代码作为教程载体根目录的 pythonlegacy.mdfilename: learnpythonlegacy.py可视为一份完整的 Python 2 脚本hu/pythonlegacy.md 等各语言译本ar、cs、el、fr、it、ja、pt-br、tr、vi、zh-cn 目录下均有 Python 3 教程译本与之互为参照。如果你想学习现代 Python建议直接阅读仓库根目录的 Python 3 教程或 zh-cn/python.md若仍需维护 Python 2 遗留代码可结合本文完整代码示例在本地 Python 2.7 环境中逐段运行验证——只需注意所有.md文件均受 lint/frontmatter.py 与 lint/encoding.sh 的格式约束保持 UTF-8 编码与规范的 frontmatter 结构即可。赞分享文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载相关推荐Python 2 语法速成教程精读learnxinyminutes-docs 法语版《Python (legacy)》全解析Python 2 语法速成教程精读learnxinyminutes docs 法语版《Python legacy 》全解析 本篇技术指南以 learnxiny文档教程learnxinyminutes-docs 仓库精读C 语言完整语法速成指南基于 fr/c.md 全解析learnxinyminutes docs 仓库精读C 语言完整语法速成指南基于 fr/c.md 全解析 本指南以 learnxinyminutes do文档教程Python 3 编程语言速成指南learnxinyminutes-docs 阿拉伯语版深度全解Python 3 编程语言速成指南learnxinyminutes docs 阿拉伯语版深度全解 本篇技术指南基于 learnxinyminutes docs文档教程上一篇7字重开源字体完全指南从入门到精通下一篇7个技巧让Genymotion突破ARM应用运行限制开发者与玩家的跨架构解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表