diff --git a/README.md b/README.md index 1a256a54..9feb7cbb 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ [![Github downloads](https://img.shields.io/github/downloads/yidao620c/python3-cookbook/total.svg)](https://github.com/yidao620c/python3-cookbook/releases/latest) [![GitHub release](https://img.shields.io/github/release/yidao620c/python3-cookbook.svg)](https://github.com/yidao620c/python3-cookbook/releases) - -# 《Python Cookbook》 3rd Edition 翻译 +# 《Python Cookbook in Chinese》 3rd Edition 翻译 《Python Cookbook》3rd 中文版3.0.0正式发布啦 ^_^! ——2017/12/07 @@ -16,6 +15,16 @@ * 中文简体版PDF下载地址: * 中文繁体版PDF下载地址: +## 关于作者David Beazley + +本书作者是David Beazley大神,一位独立的计算机科学家、教育家,以及有着35年开发经验的软件开发者。 +他在Python社区一直都很活跃,编写了很多的[python包](http://www.dabeaz.com/software.html), +发表了很多的公开[演讲视频](http://www.dabeaz.com/talks.html) 以及 +[编程教程](http://www.dabeaz.com/tutorials.html)。 +同时还是[Python Essential Reference](http://www.dabeaz.com/per.html) 以及 +[ Python Cookbook (O'Reilly Media)](http://www.dabeaz.com/cookbook.html)的作者。 + +David Beazley大神的博客地址: ## 译者的话 diff --git a/cookbook/c03/p07_inf_nan.py b/cookbook/c03/p07_inf_nan.py index 322033e5..3516aea4 100644 --- a/cookbook/c03/p07_inf_nan.py +++ b/cookbook/c03/p07_inf_nan.py @@ -16,7 +16,7 @@ def inf_nan(): print(a * 10 == a) print(10 / a) - # undifined + # undefined print(a / a) print(a + b) diff --git a/source/aboutme.rst b/source/aboutme.rst index 3d6e1457..9c1123fe 100644 --- a/source/aboutme.rst +++ b/source/aboutme.rst @@ -12,5 +12,8 @@ -------------------------------------------- -.. image:: https://xnstatic-1253397658.file.myqcloud.com/weixin1.png +**欢迎关注我的个人公众号“飞污熊”,我会定期分享一些自己的Python学习笔记和心得。** + +.. image:: https://github.com/yidao620c/python3-cookbook/raw/master/exts/wuxiong.jpg + diff --git a/source/c01/p01_unpack_sequence_into_separate_variables.rst b/source/c01/p01_unpack_sequence_into_separate_variables.rst index 626ac848..73213b43 100644 --- a/source/c01/p01_unpack_sequence_into_separate_variables.rst +++ b/source/c01/p01_unpack_sequence_into_separate_variables.rst @@ -11,7 +11,7 @@ 解决方案 ---------- 任何的序列(或者是可迭代对象)可以通过一个简单的赋值操作来分解为单独的变量。 -唯一的要求就是变量的总数和结构必须与序列相吻合。 +唯一的要求是,变量的总数和结构必须与序列保持一致。 代码示例: @@ -74,7 +74,7 @@ 'o' >>> -有时候,你可能只想解压一部分,丢弃其他的值。对于这种情况 Python 并没有提供特殊的语法。 +有时候,你可能只想解压其中的一部分而丢弃其他的值。对于这种情况 Python 并没有提供特殊的语法。 但是你可以使用任意变量名去占位,到时候丢掉这些变量就行了。 代码示例: @@ -89,4 +89,4 @@ 91.1 >>> -你必须保证你选用的那些占位变量名在其他地方没被使用到。 +但是,你必须保证你选用的那些占位变量名在其他地方没被使用到。 diff --git a/source/c01/p02_unpack_elements_from_iterables.rst b/source/c01/p02_unpack_elements_from_iterables.rst index f6318f20..f61e3ab5 100644 --- a/source/c01/p02_unpack_elements_from_iterables.rst +++ b/source/c01/p02_unpack_elements_from_iterables.rst @@ -104,7 +104,7 @@ Python 的星号表达式可以用来解决这个问题。比如,你在学习 '/usr/bin/false' >>> -有时候,你想解压一些元素后丢弃它们,你不能简单就使用 ``*`` , +有时候,你想解压一些元素后丢弃它们,你不能简单的使用 ``*`` , 但是你可以使用一个普通的废弃名称,比如 ``_`` 或者 ``ign`` (ignore)。 代码示例: @@ -145,4 +145,4 @@ Python 的星号表达式可以用来解决这个问题。比如,你在学习 >>> 然后,由于语言层面的限制,递归并不是 Python 擅长的。 -因此,最后那个递归演示仅仅是个好奇的探索罢了,对这个不要太认真了。 +因此,最后那个递归演示仅仅是个好奇的探索罢了,别太较真。 diff --git a/source/c01/p03_keep_last_n_items.rst b/source/c01/p03_keep_last_n_items.rst index d40ed19d..44b6f6bf 100644 --- a/source/c01/p03_keep_last_n_items.rst +++ b/source/c01/p03_keep_last_n_items.rst @@ -11,7 +11,8 @@ 解决方案 ---------- 保留有限历史记录正是 ``collections.deque`` 大显身手的时候。比如,下面的代码在多行上面做简单的文本匹配, -并返回匹配所在行的最后N行: +并返回匹配所在行及其前面的N行: + .. code-block:: python @@ -85,4 +86,4 @@ >>> q.popleft() 4 -在队列两端插入或删除元素时间复杂度都是 ``O(1)`` ,区别于列表,在列表的开头插入或删除元素的时间复杂度为 ``O(N)`` 。 +在队列两端插入或删除元素的时间复杂度都是 ``O(1)`` 。列表则不同,在列表的开头插入或删除元素的时间复杂度是 ``O(N)`` 。 diff --git a/source/c01/p04_find_largest_or_smallest_n_items.rst b/source/c01/p04_find_largest_or_smallest_n_items.rst index a30ea9d4..8f7f9728 100644 --- a/source/c01/p04_find_largest_or_smallest_n_items.rst +++ b/source/c01/p04_find_largest_or_smallest_n_items.rst @@ -72,6 +72,6 @@ heapq 模块有两个函数:``nlargest()`` 和 ``nsmallest()`` 可以完美解 需要在正确场合使用函数 ``nlargest()`` 和 ``nsmallest()`` 才能发挥它们的优势 (如果 N 快接近集合大小了,那么使用排序操作会更好些)。 -尽管你没有必要一定使用这里的方法,但是堆数据结构的实现是一个很有趣并且值得你深入学习的东西。 +尽管你没有必要一定使用这里的方法,但是堆数据结构的实现很有趣,值得深入学习。 基本上只要是数据结构和算法书籍里面都会有提及到。 ``heapq`` 模块的官方文档里面也详细的介绍了堆数据结构底层的实现细节。 diff --git a/source/c01/p08_calculating_with_dict.rst b/source/c01/p08_calculating_with_dict.rst index e8e18f9b..a4de6910 100644 --- a/source/c01/p08_calculating_with_dict.rst +++ b/source/c01/p08_calculating_with_dict.rst @@ -69,7 +69,7 @@ max(prices.values()) # Returns 612.78 不幸的是,通常这个结果同样也不是你想要的。 -你可能还想要知道对应的键的信息(比如那种股票价格是最低的?)。 +你可能还想要知道对应的键的信息(比如哪种股票价格是最低的?)。 你可以在 ``min()`` 和 ``max()`` 函数中提供 ``key`` 函数参数来获取最小值或最大值对应的键的信息。比如: @@ -89,7 +89,7 @@ 这样的话你就能通过一条简单的语句就能很轻松的实现在字典上的求最值和排序操作了。 需要注意的是在计算操作中使用到了 (值,键) 对。当多个实体拥有相同的值的时候,键会决定返回结果。 -比如,在执行 ``min()`` 和 ``max()`` 操作的时候,如果恰巧最小或最大值有重复的,那么拥有最小或最大键的实体会返回: +比如,在执行 ``min()`` 和 ``max()`` 操作的时候,如果恰巧最小或最大值有重复的,则返回拥有最小或最大键的实体: .. code-block:: python diff --git a/source/c01/p09_find_commonalities_in_dicts.rst b/source/c01/p09_find_commonalities_in_dicts.rst index 4c137afd..7c248ce1 100644 --- a/source/c01/p09_find_commonalities_in_dicts.rst +++ b/source/c01/p09_find_commonalities_in_dicts.rst @@ -5,7 +5,7 @@ ---------- 问题 ---------- -怎样在两个字典中寻寻找相同点(比如相同的键、相同的值等等)? +怎样在两个字典中寻找相同点(比如相同的键、相同的值等等)? ---------- 解决方案 @@ -59,5 +59,5 @@ 这个对象同样也支持集合操作,并且可以被用来查找两个字典有哪些相同的键值对。 尽管字典的 ``values()`` 方法也是类似,但是它并不支持这里介绍的集合操作。 -某种程度上是因为值视图不能保证所有的值互不相同,这样会导致某些集合操作会出现问题。 -不过,如果你硬要在值上面执行这些集合操作的话,你可以先将值集合转换成 set,然后再执行集合运算就行了。 +某种程度上是因为值视图并不能保证所有的值互不相同,这样会导致某些集合操作出现问题。 +不过,如果你硬要在值上面执行这些集合操作的话,可以先将值集合转换成 set,然后再执行集合运算。 diff --git a/source/c01/p10_remove_duplicates_from_seq_order.rst b/source/c01/p10_remove_duplicates_from_seq_order.rst index 11855873..58927c17 100644 --- a/source/c01/p10_remove_duplicates_from_seq_order.rst +++ b/source/c01/p10_remove_duplicates_from_seq_order.rst @@ -70,7 +70,7 @@ 然而,这种方法不能维护元素的顺序,生成的结果中的元素位置被打乱。而上面的方法可以避免这种情况。 在本节中我们使用了生成器函数让我们的函数更加通用,不仅仅是局限于列表处理。 -比如,如果如果你想读取一个文件,消除重复行,你可以很容易像这样做: +比如,如果你想读取一个文件,消除重复行,你可以很容易像这样做: .. code-block:: python diff --git a/source/c01/p11_naming_slice.rst b/source/c01/p11_naming_slice.rst index 0b682f9f..9ffc2264 100644 --- a/source/c01/p11_naming_slice.rst +++ b/source/c01/p11_naming_slice.rst @@ -32,8 +32,8 @@ 讨论 ---------- 一般来讲,代码中如果出现大量的硬编码下标会使得代码的可读性和可维护性大大降低。 -比如,如果你回过来看看一年前你写的代码,你会摸着脑袋想那时候自己到底想干嘛啊。 -这是一个很简单的解决方案,它让你更加清晰的表达代码的目的。 +比如,如果你回过来看看一年前你写的代码,你会摸着脑袋想自己那时候到底在想什么啊。 +下面这个很简单的解决方案,可以让你更加清晰地表达代码的目的。 内置的 ``slice()`` 函数创建了一个切片对象。所有使用切片的地方都可以使用切片对象。比如: @@ -67,7 +67,7 @@ 另外,你还可以通过调用切片的 ``indices(size)`` 方法将它映射到一个已知大小的序列上。 这个方法返回一个三元组 ``(start, stop, step)`` ,所有的值都会被缩小,直到适合这个已知序列的边界为止。 -这样,使用的时就不会出现 ``IndexError`` 异常。比如: +(这样在使用的时就不会出现 ``IndexError`` 异常)。比如: .. code-block:: python diff --git a/source/c01/p13_sort_list_of_dicts_by_key.rst b/source/c01/p13_sort_list_of_dicts_by_key.rst index 840f140a..ae1ffde1 100644 --- a/source/c01/p13_sort_list_of_dicts_by_key.rst +++ b/source/c01/p13_sort_list_of_dicts_by_key.rst @@ -69,7 +69,7 @@ ``itemgetter()`` 函数就是负责创建这个 ``callable`` 对象的。 ``operator.itemgetter()`` 函数有一个被 ``rows`` 中的记录用来查找值的索引参数。可以是一个字典键名称, -一个整形值或者任何能够传入一个对象的 ``__getitem__()`` 方法的值。 +一个整型值或者任何能够传入一个对象的 ``__getitem__()`` 方法的值。 如果你传入多个索引参数给 ``itemgetter()`` ,它生成的 ``callable`` 对象会返回一个包含所有元素值的元组, 并且 ``sorted()`` 函数会根据这个元组中元素顺序去排序。 但你想要同时在几个字段上面进行排序(比如通过姓和名来排序,也就是例子中的那样)的时候这种方法是很有用的。 diff --git a/source/c01/p14_sort_objects_without_compare_support.rst b/source/c01/p14_sort_objects_without_compare_support.rst index 8241d256..fa6b8606 100644 --- a/source/c01/p14_sort_objects_without_compare_support.rst +++ b/source/c01/p14_sort_objects_without_compare_support.rst @@ -45,7 +45,7 @@ 选择使用 lambda 函数或者是 ``attrgetter()`` 可能取决于个人喜好。 但是, ``attrgetter()`` 函数通常会运行的快点,并且还能同时允许多个字段进行比较。 这个跟 ``operator.itemgetter()`` 函数作用于字典类型很类似(参考1.13小节)。 -例如,如果 ``User`` 实例还有一个 ``first_name`` 和 ``last_name`` 属性,那么可以向下面这样排序: +例如,如果 ``User`` 实例还有一个 ``first_name`` 和 ``last_name`` 属性,那么可以像下面这样排序: .. code-block:: python diff --git a/source/c01/p17_extract_subset_of_dict.rst b/source/c01/p17_extract_subset_of_dict.rst index 693dff5d..f657d5db 100644 --- a/source/c01/p17_extract_subset_of_dict.rst +++ b/source/c01/p17_extract_subset_of_dict.rst @@ -37,7 +37,7 @@ p1 = dict((key, value) for key, value in prices.items() if value > 200) 但是,字典推导方式表意更清晰,并且实际上也会运行的更快些 -(在这个例子中,实际测试几乎比 ``dict()`` 函数方式快整整一倍)。 +(在这个例子中,实际测试几乎比 ``dict()`` 函数方式快了一倍多)。 有时候完成同一件事会有多种方式。比如,第二个例子程序也可以像这样重写: diff --git a/source/c02/p15_interpolating_variables_in_strings.rst b/source/c02/p15_interpolating_variables_in_strings.rst index b479fbe9..42e03fe4 100644 --- a/source/c02/p15_interpolating_variables_in_strings.rst +++ b/source/c02/p15_interpolating_variables_in_strings.rst @@ -106,7 +106,7 @@ Python并没有对在字符串中简单替换变量值提供直接的支持。 >>> name = 'Guido' >>> n = 37 - >>> '%(name) has %(n) messages.' % vars() + >>> '%{name} has %{n} messages.' % vars() 'Guido has 37 messages.' >>> diff --git a/source/c03/p07_infinity_and_nan.rst b/source/c03/p07_infinity_and_nan.rst index 0d23e026..b82cbb04 100644 --- a/source/c03/p07_infinity_and_nan.rst +++ b/source/c03/p07_infinity_and_nan.rst @@ -81,7 +81,7 @@ NaN值会在所有操作中传播,而不会产生异常。比如: nan >>> -NaN值的一个特别的地方时它们之间的比较操作总是返回False。比如: +NaN值的一个特别的地方是它们之间的比较操作总是返回False。比如: .. code-block:: python diff --git a/source/c03/p14_date_range_for_current_month.rst b/source/c03/p14_date_range_for_current_month.rst index 12df3fbb..b37515d2 100644 --- a/source/c03/p14_date_range_for_current_month.rst +++ b/source/c03/p14_date_range_for_current_month.rst @@ -35,8 +35,8 @@ >>> a_day = timedelta(days=1) >>> first_day, last_day = get_month_range() >>> while first_day < last_day: - ... print(first_day) - ... first_day += a_day + ... print(first_day) + ... first_day += a_day ... 2012-08-01 2012-08-02 diff --git a/source/c04/p02_delegating_iteration.rst b/source/c04/p02_delegating_iteration.rst index de8581b9..8701a78c 100644 --- a/source/c04/p02_delegating_iteration.rst +++ b/source/c04/p02_delegating_iteration.rst @@ -48,7 +48,7 @@ Python的迭代器协议需要 ``__iter__()`` 方法返回一个实现了 ``__next__()`` 方法的迭代器对象。 如果你只是迭代遍历其他容器的内容,你无须担心底层是怎样实现的。你所要做的只是传递迭代请求既可。 -这里的 ``iter()`` 函数的使用简化了代码, +这里的 ``iter()`` 函数使用了简化的代码, ``iter(s)`` 只是简单的通过调用 ``s.__iter__()`` 方法来返回对应的迭代器对象, 就跟 ``len(s)`` 会调用 ``s.__len__()`` 原理是一样的。 diff --git a/source/c04/p08_skip_first_part_of_iterable.rst b/source/c04/p08_skip_first_part_of_iterable.rst index f56697f9..0552778c 100644 --- a/source/c04/p08_skip_first_part_of_iterable.rst +++ b/source/c04/p08_skip_first_part_of_iterable.rst @@ -12,7 +12,7 @@ ---------- ``itertools`` 模块中有一些函数可以完成这个任务。 首先介绍的是 ``itertools.dropwhile()`` 函数。使用时,你给它传递一个函数对象和一个可迭代对象。 -它会返回一个迭代器对象,丢弃原有序列中直到函数返回Flase之前的所有元素,然后返回后面所有元素。 +它会返回一个迭代器对象,丢弃原有序列中直到函数返回False之前的所有元素,然后返回后面所有元素。 为了演示,假定你在读取一个开始部分是几行注释的源文件。比如: @@ -41,7 +41,7 @@ >>> from itertools import dropwhile >>> with open('/etc/passwd') as f: - ... for line in dropwhile(lambda line: not line.startswith('#'), f): + ... for line in dropwhile(lambda line: line.startswith('#'), f): ... print(line, end='') ... nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false diff --git a/source/c04/p16_replace_infinite_while_loops_with_iterator.rst b/source/c04/p16_replace_infinite_while_loops_with_iterator.rst index 1a3222a3..b7902fb8 100644 --- a/source/c04/p16_replace_infinite_while_loops_with_iterator.rst +++ b/source/c04/p16_replace_infinite_while_loops_with_iterator.rst @@ -11,7 +11,7 @@ ---------- 解决方案 ---------- -一个常见的IO操作程序可能会想下面这样: +一个常见的IO操作程序可能会像下面这样: .. code-block:: python diff --git a/source/c05/p01_read_write_text_data.rst b/source/c05/p01_read_write_text_data.rst index a5e58c7a..2f7e0d43 100644 --- a/source/c05/p01_read_write_text_data.rst +++ b/source/c05/p01_read_write_text_data.rst @@ -63,7 +63,7 @@ latin-1是字节0-255到U+0000至U+00FF范围内Unicode字符的直接映射。 ---------- 讨论 ---------- -读写文本文件一般来讲是比较简单的。但是也几点是需要注意的。 +读写文本文件一般来讲是比较简单的。但是也有几点是需要注意的。 首先,在例子程序中的with语句给被使用到的文件创建了一个上下文环境, 但 ``with`` 控制块结束时,文件会自动关闭。你也可以不使用 ``with`` 语句,但是这时候你就必须记得手动关闭文件: diff --git a/source/c05/p05_write_to_file_not_exist.rst b/source/c05/p05_write_to_file_not_exist.rst index 7a2afc23..03183811 100644 --- a/source/c05/p05_write_to_file_not_exist.rst +++ b/source/c05/p05_write_to_file_not_exist.rst @@ -5,7 +5,7 @@ ---------- 问题 ---------- -你想像一个文件中写入数据,但是前提必须是这个文件在文件系统上不存在。 +你想向一个文件中写入数据,但是前提必须是这个文件在文件系统上不存在。 也就是不允许覆盖已存在的文件内容。 ---------- diff --git a/source/c06/p01_read_write_csv_data.rst b/source/c06/p01_read_write_csv_data.rst index 9f015b52..a65cf5d6 100644 --- a/source/c06/p01_read_write_csv_data.rst +++ b/source/c06/p01_read_write_csv_data.rst @@ -42,6 +42,7 @@ .. code-block:: python from collections import namedtuple + import csv with open('stock.csv') as f: f_csv = csv.reader(f) headings = next(f_csv) diff --git a/source/c06/p05_turning_dictionary_into_xml.rst b/source/c06/p05_turning_dictionary_into_xml.rst index 2dafed71..930b4d36 100644 --- a/source/c06/p05_turning_dictionary_into_xml.rst +++ b/source/c06/p05_turning_dictionary_into_xml.rst @@ -18,15 +18,15 @@ from xml.etree.ElementTree import Element def dict_to_xml(tag, d): - ''' - Turn a simple dict of key/value pairs into XML - ''' - elem = Element(tag) - for key, val in d.items(): - child = Element(key) - child.text = str(val) - elem.append(child) - return elem + ''' + Turn a simple dict of key/value pairs into XML + ''' + elem = Element(tag) + for key, val in d.items(): + child = Element(key) + child.text = str(val) + elem.append(child) + return elem 下面是一个使用例子: diff --git a/source/c06/p06_parse_modify_rewrite_xml.rst b/source/c06/p06_parse_modify_rewrite_xml.rst index 72fa4ef7..df0193a5 100644 --- a/source/c06/p06_parse_modify_rewrite_xml.rst +++ b/source/c06/p06_parse_modify_rewrite_xml.rst @@ -5,7 +5,7 @@ ---------- 问题 ---------- -你想读取一个XML文档,对它最一些修改,然后将结果写回XML文档。 +你想读取一个XML文档,对它做一些修改,然后将结果写回XML文档。 ---------- 解决方案 diff --git a/source/c06/p09_decode_encode_hexadecimal_digits.rst b/source/c06/p09_decode_encode_hexadecimal_digits.rst index a34c8b16..55ad1795 100644 --- a/source/c06/p09_decode_encode_hexadecimal_digits.rst +++ b/source/c06/p09_decode_encode_hexadecimal_digits.rst @@ -47,7 +47,7 @@ 而 ``binascii`` 模块中的函数大小写都能处理。 还有一点需要注意的是编码函数所产生的输出总是一个字节字符串。 -如果想强制以Unicode形式输出,你需要增加一个额外的界面步骤。例如: +如果想强制以Unicode形式输出,你需要增加一个额外的解码步骤。例如: .. code-block:: python diff --git a/source/c07/p04_return_multiple_values_from_function.rst b/source/c07/p04_return_multiple_values_from_function.rst index 03cf1622..2952fbe9 100644 --- a/source/c07/p04_return_multiple_values_from_function.rst +++ b/source/c07/p04_return_multiple_values_from_function.rst @@ -15,7 +15,7 @@ .. code-block:: python >>> def myfun(): - ... return 1, 2, 3 + ... return 1, 2, 3 ... >>> a, b, c = myfun() >>> a diff --git a/source/c08/p04_save_memory_when_create_large_number_instances.rst b/source/c08/p04_save_memory_when_create_large_number_instances.rst index d6599895..94982535 100644 --- a/source/c08/p04_save_memory_when_create_large_number_instances.rst +++ b/source/c08/p04_save_memory_when_create_large_number_instances.rst @@ -23,7 +23,7 @@ 当你定义 ``__slots__`` 后,Python就会为实例使用一种更加紧凑的内部表示。 实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典,这跟元组或列表很类似。 -在 ``__slots__`` 中列出的属性名在内部被映射到这个数组的指定小标上。 +在 ``__slots__`` 中列出的属性名在内部被映射到这个数组的指定下标上。 使用slots一个不好的地方就是我们不能再给实例添加新的属性了,只能使用在 ``__slots__`` 中定义的那些属性名。 ---------- diff --git a/source/c08/p05_encapsulating_names_in_class.rst b/source/c08/p05_encapsulating_names_in_class.rst index 4f8ef5d7..bb05f99b 100644 --- a/source/c08/p05_encapsulating_names_in_class.rst +++ b/source/c08/p05_encapsulating_names_in_class.rst @@ -80,6 +80,6 @@ Python并不会真的阻止别人访问内部名称。但是如果你这么做 lambda_ = 2.0 # Trailing _ to avoid clash with lambda keyword -这里我们并不使用单下划线前缀的原因是它避免误解它的使用初衷 -(如使用单下划线前缀的目的是为了防止命名冲突而不是指明这个属性是私有的)。 +这里我们并不使用单下划线前缀的原因是避免误解它的使用初衷 +(如使用单下划线后缀的目的是为了防止命名冲突而不是指明这个属性是私有的)。 通过使用单下划线后缀可以解决这个问题。 diff --git a/source/c08/p06_create_managed_attributes.rst b/source/c08/p06_create_managed_attributes.rst index 3d6075c3..cde38194 100644 --- a/source/c08/p06_create_managed_attributes.rst +++ b/source/c08/p06_create_managed_attributes.rst @@ -17,7 +17,7 @@ class Person: def __init__(self, first_name): - self._first_name = first_name + self.first_name = first_name # Getter function @property @@ -110,7 +110,7 @@ property的一个关键特征是它看上去跟普通的attribute没什么两样 >>> -通常来讲,你不会直接取调用fget或者fset,它们会在访问property的时候自动被触发。 +通常来讲,你不会直接去调用fget或者fset,它们会在访问property的时候自动被触发。 只有当你确实需要对attribute执行其他额外的操作的时候才应该使用到property。 有时候一些从其他编程语言(比如Java)过来的程序员总认为所有访问都应该通过getter和setter, diff --git a/source/c08/p25_creating_cached_instances.rst b/source/c08/p25_creating_cached_instances.rst index 6af8ba87..583c87bc 100644 --- a/source/c08/p25_creating_cached_instances.rst +++ b/source/c08/p25_creating_cached_instances.rst @@ -10,7 +10,7 @@ ---------- 解决方案 ---------- -这种通常是因为你希望相同参数创建的对象时单例的。 +这种通常是因为你希望相同参数创建的对象是单例的。 在很多库中都有实际的例子,比如 ``logging`` 模块,使用相同的名称创建的 ``logger`` 实例永远只有一个。例如: .. code-block:: python diff --git a/source/c09/p21_avoid_repetitive_property_methods.rst b/source/c09/p21_avoid_repetitive_property_methods.rst index 5482ab8b..358cb75a 100644 --- a/source/c09/p21_avoid_repetitive_property_methods.rst +++ b/source/c09/p21_avoid_repetitive_property_methods.rst @@ -76,7 +76,7 @@ 看上去有点难理解,其实它所做的仅仅就是为你生成属性并返回这个属性对象。 因此,当在一个类中使用它的时候,效果跟将它里面的代码放到类定义中去是一样的。 尽管属性的 ``getter`` 和 ``setter`` 方法访问了本地变量如 ``name`` , ``expected_type`` -以及 ``storate_name`` ,这个很正常,这些变量的值会保存在闭包当中。 +以及 ``storage_name`` ,这个很正常,这些变量的值会保存在闭包当中。 我们还可以使用 ``functools.partial()`` 来稍稍改变下这个例子,很有趣。例如,你可以像下面这样: diff --git a/source/c10/p03_import_submodules_by_relative_names.rst b/source/c10/p03_import_submodules_by_relative_names.rst index 043a00f6..bb2dde6c 100644 --- a/source/c10/p03_import_submodules_by_relative_names.rst +++ b/source/c10/p03_import_submodules_by_relative_names.rst @@ -59,7 +59,7 @@ from . import grok # OK import grok # Error (not found) -像mypackage.A这样使用绝对路径名的不利之处是这将顶层包名硬编码到你的源码中。如果你想重新组织它,你的代码将更脆,很难工作。 举个例子,如果你改变了包名,你就必须检查所有文件来修正源码。 同样,硬编码的名称会使移动代码变得困难。举个例子,也许有人想安装两个不同版本的软件包,只通过名称区分它们。 如果使用相对导入,那一切都ok,然而使用绝对路径名很可能会出问题。 +类似于mypackage.A这样使用绝对路径名的缺点是,它会把顶层包名硬编码到源码中。如果你想重新组织它,那就适得其反——你的代码会更为脆弱,难以运作。 举例来说,如果你改变了包名,你想要修正源码就必须检查所有文件来。 同样,硬编码的名称会使移动代码变得困难。举个例子,也许有人想安装两个不同版本的软件包,只通过名称区分它们。 如果使用相对导入,那一切都ok,然而使用绝对路径名很可能会出问题。 import语句的 ``.`` 和 ``..`` 看起来很滑稽, 但它指定目录名.为当前目录,..B为目录../B。这种语法只适用于import。 diff --git a/source/c10/p12_patching_modules_on_import.rst b/source/c10/p12_patching_modules_on_import.rst index 9166ba10..5356e2ba 100644 --- a/source/c10/p12_patching_modules_on_import.rst +++ b/source/c10/p12_patching_modules_on_import.rst @@ -109,7 +109,7 @@ 本节中的 ``PostImportFinder`` 的作用并不是加载模块,而是自带导入完成后触发相应的动作。 实际的导入被委派给位于sys.meta_path中的其他查找器。 ``PostImportLoader`` 类中的 ``imp.import_module()`` 函数被递归的调用。 -为了避免陷入无线循环,``PostImportFinder`` 保持了一个所有被加载过的模块集合。 +为了避免陷入无限循环,``PostImportFinder`` 保持了一个所有被加载过的模块集合。 如果一个模块名存在就会直接被忽略掉。 当一个模块被 ``imp.import_module()`` 加载后, diff --git a/source/c11/p02_creating_tcp_server.rst b/source/c11/p02_creating_tcp_server.rst index 4eb29dff..670b06c6 100644 --- a/source/c11/p02_creating_tcp_server.rst +++ b/source/c11/p02_creating_tcp_server.rst @@ -81,7 +81,7 @@ serv.serve_forever() 使用fork或线程服务器有个潜在问题就是它们会为每个客户端连接创建一个新的进程或线程。 -由于客户端连接数是没有限制的,因此一个恶意的黑客可以同时发送大量的连接让你的服务器奔溃。 +由于客户端连接数是没有限制的,因此一个恶意的黑客可以同时发送大量的连接让你的服务器崩溃。 如果你担心这个问题,你可以创建一个预先分配大小的工作线程池或进程池。 你先创建一个普通的非线程服务器,然后在一个线程池中使用 ``serve_forever()`` 方法来启动它们。 diff --git a/source/c11/p11_pass_socket_file_descriptor_between_processes.rst b/source/c11/p11_pass_socket_file_descriptor_between_processes.rst index 0870db69..58c4923a 100644 --- a/source/c11/p11_pass_socket_file_descriptor_between_processes.rst +++ b/source/c11/p11_pass_socket_file_descriptor_between_processes.rst @@ -6,7 +6,7 @@ 问题 ---------- 你有多个Python解释器进程在同时运行,你想将某个打开的文件描述符从一个解释器传递给另外一个。 -比如,假设有个服务器进程相应连接请求,但是实际的相应逻辑是在另一个解释器中执行的。 +比如,假设有个服务器进程相应连接请求,但是实际的响应逻辑是在另一个解释器中执行的。 ---------- 解决方案 diff --git a/source/c15/p01_access_ccode_using_ctypes.rst b/source/c15/p01_access_ccode_using_ctypes.rst index 6b425972..4e3005af 100644 --- a/source/c15/p01_access_ccode_using_ctypes.rst +++ b/source/c15/p01_access_ccode_using_ctypes.rst @@ -255,7 +255,7 @@ >>> a = array.array('d',[1,2,3]) >>> a array('d', [1.0, 2.0, 3.0]) - >>> ptr_ = a.buffer_info() + >>> ptr, _ = a.buffer_info() >>> ptr 4298687200 >>> ctypes.cast(ptr, ctypes.POINTER(ctypes.c_double)) diff --git a/source/c15/p02_write_simple_c_extension_module.rst b/source/c15/p02_write_simple_c_extension_module.rst index 642231da..9ee98d75 100644 --- a/source/c15/p02_write_simple_c_extension_module.rst +++ b/source/c15/p02_write_simple_c_extension_module.rst @@ -34,7 +34,7 @@ 有了这些,下面我们演示下编写扩展函数的一个简单例子: :: - + /* pysample.c */ #include "Python.h" #include "sample.h" @@ -103,20 +103,16 @@ # setup.py from distutils.core import setup, Extension - setup(name='sample', + setup(name="sample", ext_modules=[ - Extension('sample', - ['pysample.c'], - include_dirs = ['/some/dir'], - define_macros = [('FOO','1')], - undef_macros = ['BAR'], - library_dirs = ['/usr/local/lib'], - libraries = ['sample'] + Extension("sample", + ["../sample.c", "pysample.c"], + include_dirs = ['..'], ) ] ) -为了构建最终的函数库,只需简单的使用 ``python3 buildlib.py build_ext --inplace`` 命令即可: +为了构建最终的函数库,只需简单的使用 ``python3 setup.py build_ext --inplace`` 命令即可: :: diff --git a/source/c15/p03_write_extension_function_operate_on_arrays.rst b/source/c15/p03_write_extension_function_operate_on_arrays.rst index 80cc2413..0e520746 100644 --- a/source/c15/p03_write_extension_function_operate_on_arrays.rst +++ b/source/c15/p03_write_extension_function_operate_on_arrays.rst @@ -60,6 +60,7 @@ :: >>> import array + >>> from sample import * >>> avg(array.array('d',[1,2,3])) 2.0 >>> import numpy @@ -95,9 +96,9 @@ 通过编写能接受并操作数组的代码,你可以编写很好的兼容这些应用程序的自定义代码, 而不是只能兼容你自己的代码。 -代码的关键点在于 ``PyBuffer_GetBuffer()`` 函数。 +代码的关键点在于 ``PyObject_GetBuffer()`` 函数。 给定一个任意的Python对象,它会试着去获取底层内存信息,它简单的抛出一个异常并返回-1. -传给 ``PyBuffer_GetBuffer()`` 的特殊标志给出了所需的内存缓冲类型。 +传给 ``PyObject_GetBuffer()`` 的特殊标志给出了所需的内存缓冲类型。 例如,``PyBUF_ANY_CONTIGUOUS`` 表示是一个连续的内存区域。 对于数组、字节字符串和其他类似对象而言,一个 ``Py_buffer`` 结构体包含了所有底层内存的信息。 diff --git a/source/c15/p10_wrap_existing_c_code_with_cython.rst b/source/c15/p10_wrap_existing_c_code_with_cython.rst index 68738b13..56c42675 100644 --- a/source/c15/p10_wrap_existing_c_code_with_cython.rst +++ b/source/c15/p10_wrap_existing_c_code_with_cython.rst @@ -10,7 +10,7 @@ ---------- 解决方案 ---------- -使用Cython构建一个扩展模块看上去很手写扩展有些类似, +使用Cython构建一个扩展模块看上去和手写扩展有些类似, 因为你需要创建很多包装函数。不过,跟前面不同的是,你不需要在C语言中做这些——代码看上去更像是Python。 作为准备,假设本章介绍部分的示例代码已经被编译到某个叫 ``libsample`` 的C函数库中了。 @@ -178,7 +178,7 @@ def gcd(unsigned int x, unsigned int y): return csample.gcd(x,y) -对于简单的函数,你并不需要去做太多的时。 +对于简单的函数,你并不需要去做太多的事。 Cython会生成包装代码来正确的转换参数和返回值。 绑定到属性上的C数据类型是可选的。不过,如果你包含了它们,你可以另外做一些错误检查。 例如,如果有人使用负数来调用这个函数,会抛出一个异常: diff --git a/source/c15/p11_use_cython_to_write_high_performance_array_operation.rst b/source/c15/p11_use_cython_to_write_high_performance_array_operation.rst index ba925b4d..737b735e 100644 --- a/source/c15/p11_use_cython_to_write_high_performance_array_operation.rst +++ b/source/c15/p11_use_cython_to_write_high_performance_array_operation.rst @@ -103,7 +103,7 @@ 3.760528204000366 >>> -正如你看到的,它要快很多——这是一个很有趣的结果,因为NumPy版本的核心代码还是用C语言写的。 +如你所见,它快了一些——考虑到NumPy版本的核心代码是用C语言写的,这还挺有趣。 ---------- 讨论