知行编程网知行编程网  2022-07-07 07:00 知行编程网 隐藏边栏 |   抢沙发  3 
文章评分 0 次,平均分 0.0

来自:Why GitHub?  

链接:https://github.com/shendeguize/GooglePythonStyleGuideCN


这是一位朋友翻译的Google Python代码风格指南,很全面。可以作为公司的code review 标准,也可以作为自己编写代码的风格指南。希望对你有帮助。

Translator: shendeguize@github

Link: https://github.com/shendeguize/GooglePythonStyleGuideCN

本翻译囿于水平,可能有不准确的地方,欢迎指出,谢谢大家

1、背景

Python是谷歌主要使用的动态语言,本风格指导列举了使用Python编程时应该做和不该做的事项(dos & don'ts)

为了帮助你正确地组织代码,我们编写了一个Vim的设置文件.对于Emacs,默认设置即可.

许多团队使用yapf自动格式工具来避免格式争议

2、Python语言规则

2.1 Lint

对代码使用<span style="font-size: 15px;">pylint</span>

2.1.1Definition(以下都译为定义)

<span style="font-size: 15px;color: rgb(0, 0, 0);">pylint</span>是一个用于在Python代码中发现bug和代码风格问题的工具,,<span style="font-size: 15px;color: rgb(0, 0, 0);">pylint</span>查找那些常在非动态语言(例如C或C++)编译器中捕获的问题.由于Python是动态语言,一些警告可能不正确,不过应该非常少有错误警告.

2.1.2 Pros

能够发现一些易被遗漏的错误,类似拼写错误,调用早于声明等等.

2.1.3 Cons

<span style="font-size: 15px;color: rgb(0, 0, 0);">pylint</span>并不完美,为了更好的利用工具,我们有时候需要

a. Write around it(适配上下文风格)

b. 压制一些警告

c. 优化工具

2.1.4 Decision(以下都译为建议)

确保对代码应用<span style="font-size: 15px;color: rgb(0, 0, 0);">pylint</span>

如果一些警告是不合适的,就抑制这些警告,这是为了让其他警告不会被隐藏.为了压制警告,可以设置行级别的注释:

<span style="font-size: 15px;">pylint</span>警告包含标识名(<span style="font-size: 15px;">empty-docstring</span>),谷歌专有的警告以<span style="font-size: 15px;">g-</span>开头.

如果抑制警告的原因在标识名称中表述不够清晰,请额外添加注解.

用这种方式来抑制警告的优点是我们能够简单地找到抑制的警告并且重新访问这些警告.

可以通过下述方式来获得<span style="font-size: 15px;">pylint</span>警告列表:

用下述方式来获取某个特定消息的更多具体信息:

优先使用<span style="font-size: 15px;">pylint: disable</span>而非旧方法(<span style="font-size: 15px;">pylint: disable-msg</span>)如果要抑制由于参数未使用的警告,可以在函数开头del,并注释为什么要删除这些未使用参数,仅仅一句"unused"是不够的:

其他可以用来抑制警告的方式包括用<span style="font-size: 15px;">'_'</span>作为未使用参数的标识,在参数名前增加<span style="font-size: 15px;">'unused_'</span>,或者分配这些参数到<span style="font-size: 15px;">'_'</span>.这些方式是可以的,但是已经不鼓励继续使用.前两种方式会影响到通过参数名传参的调用方式,而最后一种并不能保证参数确实未被使用.

2.2 Imports

只在import包和模块的时候使用<span style="font-size: 15px;color: rgb(0, 0, 0);">import</span>,而不要应用在单独的类或函数.(这一条对于typing_module有特别的意外)

2.2.1 定义

一个模块到另一个模块之间共享代码的复用性机制

2.2.2 Pros

命名空间管理约定简单,每个标识的源都一致性地被指明了.例如<span style="font-size: 15px;color: rgb(0, 0, 0);">x.Obj</span>表示<span style="font-size: 15px;color: rgb(0, 0, 0);">Obj</span>是在模块<span style="font-size: 15px;color: rgb(0, 0, 0);">x</span>中定义的

2.2.3 Cons

模块名可能会有冲突,一些模块名可能很长,比较不方便

2.2.4 建议

  • <span style="font-size: 15px;color: rgb(0, 0, 0);">import x</span>(当<span style="font-size: 15px;color: rgb(0, 0, 0);">x</span>是包或模块)
  • <span style="font-size: 15px;color: rgb(0, 0, 0);">from x import y</span> (当<span style="font-size: 15px;color: rgb(0, 0, 0);">x</span>是包前缀,<span style="font-size: 15px;color: rgb(0, 0, 0);">y</span>是不带前缀的模块名)
  • <span style="font-size: 15px;color: rgb(0, 0, 0);">from x import  y as z</span> (当有重复模块名<span style="font-size: 15px;color: rgb(0, 0, 0);">y</span><span style="font-size: 15px;color: rgb(0, 0, 0);">y</span>过长不利于引用的时候)
  • <span style="font-size: 15px;color: rgb(0, 0, 0);">import y as z</span> (仅在非常通用的简写的时候使用例如<span style="font-size: 15px;color: rgb(0, 0, 0);">import numpy as np</span>

<span style="font-size: 15px;color: rgb(0, 0, 0);">sound.effects.echo</span>为例:

不要使用相对引用,即便在同一包内,也使用完整包名import,这有助于避免无意重复import包.

从typing module和six.moves module import不适用上述规则

2.3 包

每一模块都要从完整路径import

2.3.1 Pros

能够避免模块名冲突以及由于模块搜索路径与作者预期不符而造成的错误引用.让查找模块更简单.

2.3.2 Cons

让部署代码时有些困难,因为包架构也需要赋值,不过对于现在的部署机制而言,这其实不是问题.

2.3.3 建议

所有的新代码都要从完整包名来import模块

import示例应该像这样:

Yes:

No:(假设文件在<span style="font-size: 15px;">doctor/who</span>中,<span style="font-size: 15px;">jodie.py</span>也在这里)

不应该假设主代码所在路径被包含在<span style="font-size: 15px;">sys.path</span>中,即使有些时候可以work.在上一例代码中,我们应该认为<span style="font-size: 15px;">import jodie</span>指的是import一个叫做<span style="font-size: 15px;">jodie</span>的第三方包或者顶级目录中的<span style="font-size: 15px;">jodie</span>,而非一个当前路径的<span style="font-size: 15px;">jodie.py</span>

2.4 异常

异常处理是允许使用的,但使用务必谨慎

2.4.1 定义

异常是一种从正常代码段控制流中跳出以处理错误或者其他异常条件的手段.

2.4.2 Pros

正常代码的控制流时不会被错误处理代码影响的.异常处理同样允许在某些情况下,控制流跳过多段代码,例如在某一步从N个嵌入函数返回结果而非强行延续错误代码.

2.4.3 Cons

可能会让控制流变的难于理解,也比较容易错过调用库函数的报错.

2.4.4 建议

异常必定遵循特定条件:

  • 使用<span style="font-size: 15px;color: rgb(0, 0, 0);">raise MyError('Error message')</span>或者<span style="font-size: 15px;color: rgb(0, 0, 0);">raise MyError()</span>,不要使用两段<span style="font-size: 15px;color: rgb(0, 0, 0);">raise MyError, 'Error message'</span>
  • 当内置异常类合理的时候,尽量使用内置异常.例如:抛出<span style="font-size: 15px;color: rgb(0, 0, 0);">ValueError</span>来表示一个像是违反预设前提(例如传参了一个负数给要求正数的情况)的程序错误发生.

不要使用<span style="font-size: 15px;color: rgb(0, 0, 0);">assert</span>来片段公共结构参数值.<span style="font-size: 15px;color: rgb(0, 0, 0);">assert</span>是用来确认内部计算正确性也不是用来表示一些预期外的事件发生的.如果异常是后续处理要求的,用<span style="font-size: 15px;color: rgb(0, 0, 0);">raise</span>语句来处理,例如:

Yes:

No:

  • 库或者包可能会定义各自的异常.当这样做的时候,必须要继承一个已经存在的异常类,异常类的名字应该以<span style="font-size: 15px;">Error</span>结尾,并且不应该引入重复(<span style="font-size: 15px;">foo.FooError</span>)

  • 永远不要用捕获全部异常的<span style="font-size: 15px;">except:</span>语句,或者捕获<span style="font-size: 15px;">Exception</span>或者<span style="font-size: 15px;">StandardError</span>除非:

    Python在这个方面容忍度很高,并且<span style="font-size: 15px;">except:</span>语句会捕获包括拼写错误,sys.exit(),Ctrl+C终止,单元测试失败和和所有你并没有想到捕获的其他异常.

    • 再次抛出这个异常
    • 在程序中异常不会继续但是会被记录以及消除(例如通过保护最外层的方式保护线程不会崩溃)的地方创造一个孤立点.
  • 最精简<span style="font-size: 15px;">try/except</span>表达式内部的代码量,<span style="font-size: 15px;">try</span>代码块里的代码体量越大,月可能会在你不希望抛出异常的代码中抛出异常,进而在这种情况下,<span style="font-size: 15px;">try/except</span>掩盖了一个真实的异常

  • 使用finally来执行代码,这些代码无论是否有异常在<span style="font-size: 15px;">try</span>代码块被抛出都会被执行.这在清理(即关闭文件)时非常有用.

  • 当捕获了异常时,用as而不是逗号分段.

2.5 全局变量

避免全局变量

2.5.1 定义

在模块级别或者作为类属性声明的变量

2.5.2 Pros

有些时候有用

2.5.3 Cons

在import的过程中,有可能改变模块行为,因为在模块首次被引入的过程中,全局变量就已经被声明

2.5.4 建议

避免全局变量

作为技术变量,模块级别的常量是允许并鼓励使用的.例如<span style="font-size: 15px;color: rgb(0, 0, 0);">MAX_HOLY_HANDGRENADE_COUNT = 3</span>, 常量必须由大写字母和下划线组成,参见下方命名规则

如果需要,全局变量需要在模块级别声明,并且通过在变量名前加<span style="font-size: 15px;color: rgb(0, 0, 0);">_</span>来使其对模块内私有化.外部对模块全局变量的访问必须通过公共模块级别函数,参见下方命名规则

2.6 内嵌/局部/内部 类和函数

内嵌局部函数或类在关闭局部变量时是可以的.内部类意识可用的.(译注:这里我的理解是当内嵌局部函数或类是和局部变量在同一个封闭作用域内是可以的.)

2.6.1 定义

类可以在方法,函数,类内定义.函数可以在方法或函数内定义.内嵌函数对封闭作用域的变量具有只读访问权限.

2.6.2 Pros

允许定义只在非常有限作用域内可用的工具类或工具函数.Very ADT-y(??符合抽象数据类型要求???),通常用于实现装饰器

2.6.3 Cons

内嵌或局部类的实例是不能被pickle的,内嵌函数或类是不能被直接测试的.嵌套会让外部函数更长并且更难读懂.

2.6.4 建议

除了一些特别声明,这些内嵌/局部/内部类和函数都是可以的.避免内嵌函数或类除了需要关闭一个局部值的时候.(译者理解可能是除了将局部变量封闭在同一个作用域的情况以外).不要把一个函数转为内嵌指示为了避免访问.在这种情况下,把函数置于模块级别并在函数名前加<span style="font-size: 15px;color: rgb(0, 0, 0);">_</span>以保证测试是可以访问该函数的.

2.7 列表推导和生成器表达式

在简单情况下是可用的

2.7.1 定义

List, Dict和Set推导生成式以及生成器表达式提供了一个简明有效的方式来生成容器和迭代器而不需要传统的循环,<span style="font-size: 15px;color: rgb(0, 0, 0);">map()</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">filter()</span>或者<span style="font-size: 15px;color: rgb(0, 0, 0);">lambda表达式</span>

2.7.2 Pros

简单地推导表达比其他的字典,列表或集合生成方法更加简明清晰.生成器表达式可以很有效率,因为完全避免了生成列表.

2.7.3 Cons

负载的推导表达式或生成器表达式很难读懂

2.7.4 建议

简单情况下使用时可以的.每个部分(mapping表达式,filter表达式等)都应该在一行内完成.多个for条款或者filter表达式是不允许的.当情况变得很复杂的适合就使用循环.

Yes:

No:

2.8 默认迭代器和运算符

对支持默认迭代器和云算法的类型例如列表,字典和文件等使用它们

2.8.1 定义

容器类型(例如字典,列表等)定义了的默认的迭代器和成员检查运算符.

Pros

默认迭代器和操作符是简单有效的,能够直接不需额外调用方法地表达操作.使用默认操作符的函数是通用的.能被用于任何支持这些操作的类型.

Cons

不能通过方法名来分辨类型,例如<span style="font-size: 15px;color: rgb(0, 0, 0);">has_key()</span>意味着字典,当然这也是一种优势.

建议

对于支持的类型诸如列表,字典和文件,使用默认迭代器和操作符.内置类型同样定义了迭代器方法.优先使用这些方法而非那些返回列表的方法.除非能够确定在遍历容器的过程中不会改变容器.不要使用Python 2专有迭代方法除非必要.

Yes:

No:

2.9 生成器

需要时使用生成器

2.9.1 定义

生成器函数返回一个迭代器,每次执行<span style="font-size: 15px;color: rgb(0, 0, 0);">yield</span>语句的时候生成一个值.在生成一个值之后,生成器函数的运行被挂起直到需要下一个值.

2.9.2 Pros

简化代码,因为局部变量和控制流在每次调用时被保留,生成器相比于一次性生成整个一个列表值要更节省内存.

2.9.3 Cons

2.9.4 建议

建议使用.在生成器函数的文档字符串中使用"Yields:"而非"Returns:"

2.10 Lambda表达式

单行代码时是可以的

2.10.1 定义

lambda在一个表达式内定义了匿名函数,而不在语句里.lambda表达式常被用于定义高阶函数(例如<span style="font-size: 15px;color: rgb(0, 0, 0);">map()</span><span style="font-size: 15px;color: rgb(0, 0, 0);">filter()</span>)使用的回调函数或者操作符.

2.10.2 Pros

方便

2.10.3 Cons

比局部函数更难读懂和debug,匿名意味着堆栈跟踪更难懂.表达性受限因为lambda函数只包含一个表达式

2.10.4 建议

对于单行代码而言,可以使用lambda表达式.如果<span style="font-size: 15px;color: rgb(0, 0, 0);">lambda</span>表达式内的代码超过60-80个字符,最好定义成为常规的内嵌函数.

对于一般的操作诸如乘法,使用<span style="font-size: 15px;color: rgb(0, 0, 0);">operator</span>模块内置函数而非重新定义匿名函数,例如使用<span style="font-size: 15px;color: rgb(0, 0, 0);">operator.mul</span>而非<span style="font-size: 15px;color: rgb(0, 0, 0);">lambda x,y: x * y</span>

2.11 条件表达式

简单情况下可以使用.

2.11.1 定义

条件表达式(也称为三元运算符)是一种更短替代if语句的机制.例如<span style="font-size: 15px;color: rgb(0, 0, 0);">x = 1 if cond else 2</span>

2.11.2 Pros

相对于if语句更短也更方便

2.11.3 Cons

比if语句可能更难读懂,当表达式很长的时候条件部分可能很难定位.

2.11.4 建议

简单情况可以使用.每个部分(真值表达式,if表达式,else表达式)必须在一行内完成.如果使用条件表达式很富的时候使用完整的if语句.

Yes:

No:

2.12 默认参数值

大多数情况下都OK

2.12.1 定义

在函数参数列表的最后可以为变量设定值,例如<span style="font-size: 15px;color: rgb(0, 0, 0);">def foo(a, b=0):</span>.如果<span style="font-size: 15px;color: rgb(0, 0, 0);">foo</span>在调用时只传入一个参数,那么<span style="font-size: 15px;color: rgb(0, 0, 0);">b</span>变量就被设定为0,如果调用时传入两个参数,那么<span style="font-size: 15px;color: rgb(0, 0, 0);">b</span>就被赋予第二个参数值.

2.12.2 Pros

通常一个函数可能会有大量默认值,但是很少会有需要修改这些默认值的时候.默认值就提供了一个很简单满足上述情况的方式,而不需要为这些少见的情况重新定义很多函数.因为Python不支持重载方法或函数,默认参数是一个很简单的方式来"假重载"行为.

2.12.3 Cons

默认参数在模块加载时就被复制.这在参数是可变对象(例如列表或字典)时引发问题.如果函数修改了这些可变对象(例如向列表尾添加元素).默认值就被改变了.

2.12.4 建议

使用时请注意以下警告----在函数或方法定义时不要将可变对象作为默认值.

Yes:

No:

2.13 属性

使用属性可以通过简单而轻量级的访问器和设定器方法来访问或设定数据.

2.13.1 定义

一种装饰器调用来在计算比较轻量级时作为标准的属性访问来获取和设定一个属性的方式

2.13.2 Pros

对于简单的属性访问,减少显式的get和set方法能够提升可读性.允许惰性计算.被认为是一种Python化的方式来维护类接口.在表现上,当直接对变量的访问更合理时,允许属性绕过所需的琐碎的访问方法.

2.13.3 Cons

在Python2中必须继承于<span style="font-size: 15px;color: rgb(0, 0, 0);">object</span>,可能会隐藏像是操作符重载之类的副作用.对于子类而言,属性可能有些迷惑性.

2.13.4 建议

在通常会有简单而且轻量级的访问和设定方法的新代码里使用属性来访问或设定数据.属性在创建时被<span style="font-size: 15px;color: rgb(0, 0, 0);">@property</span>装饰,参加装饰器

如果属性本身未被重写,带有属性的继承可能不够明晰,因而必须确保访问方法是被间接访问的,来确保子类的方法重载是被属性调用的(使用Template Method DP,译者:应是模板方法设计模式).

Yes:

2.14 True/False表达式

只要可能,就使用隐式False的if语句

2.14.1 定义

在布尔环境下,Python对某些值判定为False,一个快速的经验规律是所有"空"值都被认为是False,所以<span style="font-size: 15px;color: rgb(0, 0, 0);">0, None, [], {}, ''</span>的布尔值都是False

2.14.2 Pros

使用Python布尔类型的条件语句可读性更好而且更难出错,大多数情况下,这种方式也更快.

2.14.3 Cons

对于C/C++开发者而言可能有些奇怪

建议

如果可能的话,使用隐式False.例如使用<span style="font-size: 15px;color: rgb(0, 0, 0);">if foo:</span>而非<span style="font-size: 15px;color: rgb(0, 0, 0);">if foo != []:</span>下面列举了一些你应该牢记的警告:

  • 使用<span style="font-size: 15px;color: rgb(0, 0, 0);">if foo is None</span>(或者<span style="font-size: 15px;color: rgb(0, 0, 0);">if foo is not None</span>)来检查<span style="font-size: 15px;color: rgb(0, 0, 0);">None</span>.例如在检查一个默认值是<span style="font-size: 15px;color: rgb(0, 0, 0);">None</span>的变量或者参数是否被赋予了其他值的时候,被赋予的其他值的布尔值可能为False.
  • 不要用<span style="font-size: 15px;color: rgb(0, 0, 0);">==</span>来和布尔值为<span style="font-size: 15px;color: rgb(0, 0, 0);">False</span>的变量比较,使用<span style="font-size: 15px;color: rgb(0, 0, 0);">if not x</span>,如果需要区别<span style="font-size: 15px;color: rgb(0, 0, 0);">False</span><span style="font-size: 15px;color: rgb(0, 0, 0);">None</span>,那么使用链式的表达式如<span style="font-size: 15px;color: rgb(0, 0, 0);">if not x and x is not None</span>
  • 对于序列(如字符串,列表,元组),利用空序列为<span style="font-size: 15px;color: rgb(0, 0, 0);">False</span>的事实,故而相应地使用<span style="font-size: 15px;color: rgb(0, 0, 0);">if seq:</span><span style="font-size: 15px;color: rgb(0, 0, 0);">if not seq:</span>而非<span style="font-size: 15px;color: rgb(0, 0, 0);">if len(seq)</span><span style="font-size: 15px;color: rgb(0, 0, 0);">if not len(seq):</span>.
  • 在处理整数时,隐式的False可能会引入更多风险(例如意外地将<span style="font-size: 15px;color: rgb(0, 0, 0);">None</span>和0进行了相同的处理)你可以用一个已知是整形(并且不是<span style="font-size: 15px;color: rgb(0, 0, 0);">len()</span>的结果)的值和整数0比较.

Yes:

No:

2.15 弃用的语言特性

尽可能利用字符串方法而非<span style="font-size: 15px;color: rgb(0, 0, 0);">string</span>模块.使用函数调用语法而非<span style="font-size: 15px;color: rgb(0, 0, 0);">apply</span>.在函数参数本就是一个行内匿名函数的时候,使用列表推导表达式和for循环而非<span style="font-size: 15px;color: rgb(0, 0, 0);">filter</span><span style="font-size: 15px;color: rgb(0, 0, 0);">map</span>

2.15.1 定义

当前Python版本提供了人们普遍更倾向的构建方式.

2.15.2 建议

我们不使用任何不支持这些特性的Python版本,因而没有理由不使用新方式.

Yes:

No:

2.16 词法作用域

可以使用

2.16.1 定义

一个内嵌Python函数可以引用在闭包命名空间内定义的变量,但是不能对其复制.变量绑定是解析到使用词法作用域的,即基于静态程序文本.任何对块内命名的赋值都会让Python将对于这个命名的引用都作为局部变量,即使在使用先于赋值的情况下也是.如果有全局声明,这个命名就会被认为是全局变量.

一个使用这个特性的例子是:

2.16.2 Pros

经常可以让代码更简明优雅,尤其会让有经验的Lisp和Scheme(以及Haskell和ML还有其他)的程序要很舒服.

2.16.3 Cons

可能会导致令人迷惑的bug例如这个基于PEP-0227的例子.

所以<span style="font-size: 15px;color: rgb(0, 0, 0);">foo([1, 2, 3])</span>会打印<span style="font-size: 15px;color: rgb(0, 0, 0);">1 2 3 3</span>而非<span style="font-size: 15px;color: rgb(0, 0, 0);">1 2 3 4</span>.

2.16.4 建议

可以使用

2.17 函数和方法装饰器

在明显有好处时,谨慎明智的使用,避免<span style="font-size: 15px;color: rgb(0, 0, 0);">@staticmethod</span>,控制使用<span style="font-size: 15px;color: rgb(0, 0, 0);">@classmethod</span>

2.17.1 定义

函数和方法装饰器(也就是<span style="font-size: 15px;color: rgb(0, 0, 0);">@</span>记号).一个常见的装饰器是<span style="font-size: 15px;color: rgb(0, 0, 0);">@property</span>,用于将普通方法转换成动态计算属性.然而装饰器语法也允许用户定义装饰器,尤其对于一些函数<span style="font-size: 15px;color: rgb(0, 0, 0);">my_decorator</span>如下:

是等效于

2.17.2 Pros

能够优雅的对方法进行某种转换,而该转换可能减少一些重复代码并保持不变性等等.

2.17.3 Cons

装饰器可以对函数的参数和返回值任意操作,导致非常隐形的操作行为.此外,装饰器在import的时候就被执行,装饰器代码的实效可能非常难恢复.

2.17.4 建议

在有明显好处的地方谨慎地使用装饰器.装饰器应该和函数遵守相同的import和命名指导规则.装饰器的文档应该清晰地声明该函数为装饰器函数.并且要为装饰器函数编写单元测试.

避免装饰器自身对外部的依赖,(如不要依赖于文件,socket,数据库连接等等),这是由于在装饰器运行的时候(在import时,可能从<span style="font-size: 15px;color: rgb(0, 0, 0);">pydoc</span>或其他工具中)这些外部依赖可能不可用.一个被传入有效参数并调用的装饰器应该(尽可能)保证在任何情况下都可用.

装饰器是一种特殊的"顶级代码",参见main

永远不要使用<span style="font-size: 15px;color: rgb(0, 0, 0);">@staticmethod</span>,除非不得不整合一个API到一个已有的库,应该写一个模块等级的函数.

只在写一个命名的构造器或者一个类特定的,修改必要的全局状态(例如进程缓存等)的流程时使用<span style="font-size: 15px;color: rgb(0, 0, 0);">@classmethod</span>.

2.18 线程

不要依赖于内建类型的原子性

尽管Python内置数据类型例如字典等似乎有原子性操作,仍有一些罕见情况下,他们是非原子的(比如,如果<span style="font-size: 15px;">__hash__</span>或者<span style="font-size: 15px;">__eq__</span>被实现为Python方法),就不应该依赖于这些类型的原子性.也不应该依赖于原子变量赋值(因为这依赖于字典)

优先使用Queue模块的<span style="font-size: 15px;">Queue</span>类来作为线程之间通讯数据的方式.此外,要是用threading模块和其locking primitives(锁原语).了解条件变量的合理用法以便于使用<span style="font-size: 15px;">threading.Condition</span>而非使用更低级的锁.

2.19 过于强大的特性

尽量避免使用

2.19.1 定义

Python是一种非常灵活的语言并且提供了很多新奇的特性,诸如定制元类,访问字节码,动态编译,动态继承,对象父类重定义,import hacks,反射(例如一些对于<span style="font-size: 15px;color: rgb(0, 0, 0);">getattr()</span>的应用),系统内置的修改等等.

2.19.2 Pros

这些是非常强大的语言特性,可以让程序更紧凑

2.19.3 Cons

使用这些新特性是很诱人的.但是并不绝对必要,它们很难读很难理解.也很难debug那些在底层使用了不常见的特性的代码.对于原作者而言可能不是这样,但是再次看代码的时候,可能比更长但是更直接的代码要难.

2.19.4 定义

避免在代码中使用这些特性.

内部使用这些特性的标准库和类是可以使用的(例如<span style="font-size: 15px;color: rgb(0, 0, 0);">abc.ABCMeta</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">collections.namedtuple</span>,和<span style="font-size: 15px;color: rgb(0, 0, 0);">enum</span>)

2.20 新版本Python: Python3 和从<span style="font-size: 15px;color: rgb(0, 0, 0);">__future__</span>import

Python3已经可用了(译者:目前Python2已经不受支持了),尽管不是每个项目都准备好使用Python3,所有的代码应该兼容Python3并且在可能的情况下在Python3的环境下测试.

2.20.1 定义

Python3是Python的重大改变,尽管现有代码通常是Python2.7写成的,但可以做一些简单的事情来让代码更加明确地表达其意图,从而可以让代码更好地在Python3下运行而不用调整.

2.20.2 Pros

在考虑Python3编写的代码更清晰明确,一旦所有依赖已就绪,就可以更容易在Python3环境下运行.

2.20.3 Cons

一些人会认为默认样板有些丑,import实际不需要的特性到模块中是不常见的.

2.20.4 建议

from future imports

鼓励使用<span style="font-size: 15px;color: rgb(0, 0, 0);">from __future__ import</span>语句.所有新代码都应该包含下述代码,而现有代码应该被更新以尽可能兼容:

如果你不太熟悉这些,详细阅读这些:绝对import,新的<span style="font-size: 15px;">/</span>除法行为,和<span style="font-size: 15px;">print</span>函数

请勿省略或移除这些import,即使在模块中他们没有在使用,除非代码只用于Python3.最好总是在所有的文档中都有从future的import,来保证不会在有人使用在后续编辑时遗忘.

有其他的<span style="font-size: 15px;">from __future__</span>import语句,看喜好使用.我们的建议中不包含<span style="font-size: 15px;">unicode_literals</span>因为其并无明显优势,这是由于隐式默认的编码转换导致其在Python2.7内很多地方被引入了,必要时,大多数代码最好显式的使用<span style="font-size: 15px;">b''</span><span style="font-size: 15px;">u''</span>btyes和unicode字符串表示.(译者:这段翻译可能不准确)

The six, future, or past libraries

当项目需要支持Python2和3时,根据需求使用six,future和past.

2.21 带有类型注释的代码

可以根据PEP-484对Python3代码进行类型注释,并且在build时用类型检查工具例如pytype进行类型检查.

类型注释可以在源码中或stub pyi file中.只要可能,注释就应写在源代码中.对于第三方或拓展模块使用pyi文件.

2.21.1 定义

类型注释(也称为"类型提示")是用于函数或方法参数和返回值的:

你也可以声明用一个单独的注释来声明变量的类型:

2.21.2 Pros

类型注释提升代码的可读性和可维护性,类型检查会将很多运行错误转化为构建错误,也减少了使用过于强力特性的能力.

2.21.3 Cons

需要不断更新类型声明,对于认为有效的代码可能会报类型错误,使用类型检查可能减少使用过于强力特性的能力.

2.21.4 建议

强烈鼓励在更新代码的时候进行Python类型分析.在对公共API进行补充和修改时,包括python类型声明并通过构建系统中的pytype进行检查.对Python来说静态类型检查比较新,我们承认,一些意料外的副作用(例如错误推断的类型)可能拒绝一些项目的使用.这种情况下,鼓励作者适当地增加一个带有TODO或到bug描述当前不接搜的类型注释的链接到BUILD文件或者在代码内.

3、Python代码风格规范

3.1 分号

不要在行尾加分号,也不要用分号把两行语句合并到一行

3.2 行长度

最大行长度是80个字符

超出80字符的明确例外:

  • 长import
  • 注释中的:URL,路径,flags等
  • 不包含空格不方便分行的模块级别的长字符串常量
  • pylint的diable注释使用(如<span style="font-size: 15px;"># pylint: disable=invalid-name</span>)

不要使用反斜杠连接,除非对于需要三层或以上的上下文管理器<span style="font-size: 15px;">with</span>语句

利用Python的implicit line joining inside parentheses, brackets and braces(隐式行连接方法--括号连接,包括<span style="font-size: 15px;">(), [], {}</span>).如果必要的话,也可在表达式外面额外添加一对括号.

Yes:

当字符串不能在一行内完成时,使用括号来隐式连接行:

在注释内,如有必要,将长URL放在其本行内:

Yes:

No:

在定义一个表达式超过三行或更多的<span style="font-size: 15px;">with</span>语句时,可以使用反斜杠来分行.对于两行表达式,使用嵌套<span style="font-size: 15px;">with</span>语句:

Yes:

No:

注意上述例子中的缩进,具体参看缩进

在其他一行超过80字符的情况下,而且yapf自动格式工具也不能使分行符合要求时,允许超过80字符限制.

3.3 括号

括号合理使用

尽管不必要,但是可以在元组外加括号.再返回语句或者条件语句中不要使用括号,除非是用于隐式的连接行或者指示元组.

Yes:

No:

3.4 缩进

缩进用4个空格

缩进代码段不要使用制表符,或者混用制表符和空格.如果连接多行,多行应垂直对齐,或者再次4空格缩进(这个情况下首行括号后应该不包含代码).

Yes:

No:

3.4.1 关于尾后逗号

关于在一序列元素中的尾号逗号,只推荐在容器结束符号<span style="font-size: 15px;color: rgb(0, 0, 0);">]</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">)</span>或者<span style="font-size: 15px;color: rgb(0, 0, 0);">}</span>和最后元素不在同一行时使用.尾后逗号的存在也被用作我们Python代码自动格式化工具yapf的提示,在<span style="font-size: 15px;color: rgb(0, 0, 0);">,</span>最后元素之后出现的时候来自动调整容器元素到每行一个元素.

Yes:

No:

3.5 空行

在顶级定义(函数或类)之间要间隔两行.在方法定义之间以及<span style="font-size: 15px;">class</span>所在行与第一个方法之间要空一行,<span style="font-size: 15px;">def</span>行后无空行,在函数或方法内你认为合适地方可以使用单空行.

3.6 空格

遵守标准的空格和标点排版规则.

括号<span style="font-size: 15px;">()</span>,<span style="font-size: 15px;">[]</span>,<span style="font-size: 15px;">{}</span>内部不要多余的空格.

Yes:

No:

逗号、分号、冒号前不要空格,但是在后面要加空格,除非是在行尾.

Yes:

No:

在函数调用括号的前,索引切片括号前都不加空格.

Yes:

No:

行尾不要加空格.

在赋值(<span style="font-size: 15px;">=</span>),比较(<span style="font-size: 15px;">==</span>,<span style="font-size: 15px;"><</span>,<span style="font-size: 15px;">></span>,<span style="font-size: 15px;">!=</span>,<span style="font-size: 15px;"><></span>,<span style="font-size: 15px;"><=</span>,<span style="font-size: 15px;">>=</span>,<span style="font-size: 15px;">in</span>,<span style="font-size: 15px;">not in</span>,<span style="font-size: 15px;">is</span>,<span style="font-size: 15px;">is not</span>),布尔符号(<span style="font-size: 15px;">and</span>,<span style="font-size: 15px;">or</span>,<span style="font-size: 15px;">not</span>)前后都加空格.视情况在算术运算符(<span style="font-size: 15px;">+</span>,<span style="font-size: 15px;">-</span>,<span style="font-size: 15px;">*</span>,<span style="font-size: 15px;">/</span>,<span style="font-size: 15px;">//</span>,<span style="font-size: 15px;">%</span>,<span style="font-size: 15px;">**</span>,<span style="font-size: 15px;">@</span>),前后加空格

Yes:

No:

在关键字名参数传递或定义默认参数值的时候不要在<span style="font-size: 15px;">=</span>前后加空格,只有一个例外:当类型注释存在时在定义默认参数值时<span style="font-size: 15px;">=</span>前后加空格

Yes:

No:

不要用空格来做无必要的对齐,因为这会在维护时带来不必要的负担(对于<span style="font-size: 15px;">:</span>.<span style="font-size: 15px;">#</span>,<span style="font-size: 15px;">=</span>等等).

Yes:

No:

3.7 Shebang

大部分<span style="font-size: 15px;">.py</span>文件不需要从<span style="font-size: 15px;">#!</span>行来开始.根据PEP-394,程序的主文件应该以<span style="font-size: 15px;">#!/usr/bin/python2</span><span style="font-size: 15px;">#!/usr/bin/python3</span>起始

这行被用于帮助内核找到Python解释器,但是在导入模块时会被Python忽略/只在会被直接运行的文件里有必要写.

3.8 注释和文档字符串

确保使用正确的模块,函数,方法的文档字符串和行内注释.

3.8.1 文档字符串

Python使用文档字符串来为代码生成文档.文档字符串是包,模块,类或函数的首个语句.这些字符串能够自动被<span style="font-size: 15px;color: rgb(0, 0, 0);">__doc__</span>成员方法提取并且被<span style="font-size: 15px;color: rgb(0, 0, 0);">pydoc</span>使用.(尝试在你的模块上运行<span style="font-size: 15px;color: rgb(0, 0, 0);">pydoc</span>来看看具体是什么).文档字符串使用三重双引号<span style="font-size: 15px;color: rgb(0, 0, 0);">"""</span>(根据PEP-257).文档字符串应该这样组织:一行总结(或整个文档字符串只有一行)并以句号,问好或感叹号结尾.随后是一行空行,随后是文档字符串,并与第一行的首个引号位置相对齐.更多具体格式规范如下.

3.8.2 模块

每个文件都应包含许可模板.选择合适的许可模板用于项目(例如Apache 2.0,BSD,LGPL,GPL)

文档应该以文档字符串开头,并描述模块的内容和使用方法.

3.8.3 函数和方法

在本节,"函数"所指包括方法,函数或者生成器.

函数应有文档字符串,除非符合以下所有条件:

  • 外部不可见
  • 非常短
  • 简明

文档字符串应该包含足够的信息以在无需阅读函数代码的情况下调用函数.文档字符串应该是叙事体(<span style="font-size: 15px;color: rgb(0, 0, 0);">"""Fetches rows from a Bigtable."""</span>)的而非命令式的(<span style="font-size: 15px;color: rgb(0, 0, 0);">"""Fetch rows from a Bigtable."""</span>),除了<span style="font-size: 15px;color: rgb(0, 0, 0);">@property</span>(应与attribute使用同样的风格).文档字符串应描述函数的调用语法和其意义,而非实现.对比较有技巧的地方,在代码中使用注释更合适.

覆写了基类的方法可有简单的文档字符串向读者指示被覆写方法的文档字符串例如<span style="font-size: 15px;color: rgb(0, 0, 0);">"""See base class."""</span>.这是因为没必要在很多地方重复已经在基类的文档字符串中存在的文档.不过如果覆写的方法行为实际上与被覆写方法不一致,或者需要提供细节(例如文档中表明额外的副作用),覆写方法的文档字符串至少要提供这些差别.

一个函数的不同方面应该在特定对应的分节里写入文档,这些分节如下.每一节都由以冒号结尾的一行开始, 每一节除了首行外,都应该以2或4个空格缩进并在整个文档内保持一致(译者建议4个空格以维持整体一致).如果函数名和签名足够给出足够信息并且能够刚好被一行文档字符串所描述,那么可以忽略这些节.

Args:

列出每个参数的名字.名字后应有为冒号和空格,后跟描述.如果描述太长不能够在80字符的单行内完成.那么分行并缩进2或4个空格且与全文档一致(译者同样建议4个空格)

描述应该包含参数所要求的类型,如果代码不包含类型注释的话.如果函数容许<span style="font-size: 15px;color: rgb(0, 0, 0);">*foo</span>(不定长度参数列表)或<span style="font-size: 15px;color: rgb(0, 0, 0);">**bar</span>(任意关键字参数).那么就应该在文档字符串中列举为<span style="font-size: 15px;color: rgb(0, 0, 0);">*foo</span><span style="font-size: 15px;color: rgb(0, 0, 0);">**bar</span>.

Returns:(或对于生成器是Yields:)

描述返回值的类型和含义.如果函数至少返回None,这一小节不需要.如果文档字符串以Returns或者Yields开头(例如<span style="font-size: 15px;color: rgb(0, 0, 0);">"""Returns row from Bigtable as a tuple of strings."""</span>)或首句足够描述返回值的情况下这一节可忽略.

Raises:

列出所有和接口相关的异常.对于违反文档要求而抛出的异常不应列出.(因为这会矛盾地使得违反接口要求的行为成为接口的一部分)

3.8.4 类

类定义下一行应为描述这个类的文档字符串.如果类有公共属性,应该在文档字符串中的<span style="font-size: 15px;color: rgb(0, 0, 0);">Attributes</span>节中注明,并且和函数的<span style="font-size: 15px;color: rgb(0, 0, 0);">Args</span>一节风格统一.

3.8.5 块注释和行注释

最后要在代码中注释的地方是代码技巧性的部分.如果你将要在下次code review中揭示代码.应该现在就添加注释.在复杂操作开始前,注释几行.对于不够明晰的代码在行尾注释.

为了提升易读性,行注释应该至少在代码2个空格后,并以<span style="font-size: 15px;color: rgb(0, 0, 0);">#</span>后接至少1个空格开始注释部分.

另外,不要描述代码,假定阅读代码的人比你更精通Python(他只是不知道你试图做什么).

3.8.6 标点,拼写和语法

注意标点,拼写和语法,写得好的注释要比写得差的好读.

注释应当是和叙事性文本一样可读,并具有合适的大小写和标点.在许多情况下,完整的句子要比破碎的句子更可读.更简短的注释如行尾的注释有时会不太正式,但是应该全篇保持风格一致.

尽管被代码审核人员指出在应该使用分号的地方使用了逗号是很令人沮丧的,将源代码维护在高度清楚可读的程度是很重要的.合适的标点,拼写和语法能够帮助达到这个目标.

3.9 类

如果类并非从其他基类继承而来,那么就要明确是从<span style="font-size: 15px;">object</span>继承而来,即便内嵌类也是如此.

Yes:

No:

<span style="font-size: 15px;">object</span>类继承保证了属性能够在Python2正确运行并且保护代码在Python3下出现潜在的不兼容.这样也定义了object包括<span style="font-size: 15px;">__new__</span>,<span style="font-size: 15px;">__init__</span>,<span style="font-size: 15px;">__delattr__</span>,<span style="font-size: 15px;">__getattribute__</span>,<span style="font-size: 15px;">__setattr__</span>,<span style="font-size: 15px;">__hash__</span>,<span style="font-size: 15px;">__repr__</span>,和<span style="font-size: 15px;">__str__</span>等默认特殊方法的实现.

3.10 字符串

使用<span style="font-size: 15px;">format</span><span style="font-size: 15px;">%</span>来格式化字符串,即使参数都是字符串对象,也要考虑使用<span style="font-size: 15px;">+</span>还是<span style="font-size: 15px;">%</span><span style="font-size: 15px;">format</span>.

Yes:

No:

避免使用<span style="font-size: 15px;">+</span><span style="font-size: 15px;">+=</span>操作符来在循环内累加字符串,因为字符串是不可变对象.这会造成不必要的临时变量导致运行时间以四次方增长而非线性增长.应将每个字符串都记入一个列表并使用<span style="font-size: 15px;">''.join</span>来将列表在循环结束后连接(或将每个子字符串写入<span style="font-size: 15px;">io.BytesIO</span>缓存)

Yes:

No:

在同一个文件内,字符串引号要一致,选择<span style="font-size: 15px;">''</span>或者<span style="font-size: 15px;">""</span>并且不要改变.对于需要避免<span style="font-size: 15px;">\</span>转义的时候,可以更改.

Yes:

No:

多行字符串多行字符串优先使用"""而非<span style="font-size: 15px;">'''</span>,当且只当对所有非文档字符串的多行字符串都是用<span style="font-size: 15px;">'''</span>而且对正常字符串都使用<span style="font-size: 15px;">'</span>时才可使用三单引号.docstring不论如何必须使用<span style="font-size: 15px;">"""</span>

多行字符串和其余代码的缩进方式不一致.如果需要避免在字符串中插入额外的空格,要么使用单行字符串连接或者带有<span style="font-size: 15px;">textwarp.dedent()</span>的多行字符串来移除每行的起始空格.

No:

Yes:

3.11 文件和socket

当使用结束后显式地关闭文件或socket.

不必要地打开文件,socket或其他类似文件的对象有很多弊端:

  • 他们可能会消耗有限的系统资源,例如文件描述符.如果在使用没有即使归还系统,处理很多这样对象的代码可能会浪费掉很多不应浪费的资源.
  • 保持一个文件可能会阻止其他操作诸如移动或删除.
  • 被程序共享的文件和socket可能会无意中在逻辑上已被关闭的情况下仍被读写.如果实际上已经关闭,试图读写的操作会抛出异常,这样就可以立即发现问题.

此外,当文件或socket在文件对象被销毁的同时被自动关闭的时候,是不可能将文件的生命周期和文件状态绑定的:

  • 不能保证何时会真正将文件对象销毁.不同的Python解释器使用的内存管理技术不同,例如延时垃圾处理可能会让对象的生命周期被无限期延长.
  • 可能导致意料之外地对文件对象的引用,例如在全局变量或者异常回溯中,可能会让文件对象比预计的生命周期更长.

推荐使用with语句管理文件:

对于类似文件的对象,如果不支持with语句的可以使用<span style="font-size: 15px;">contextlib.closing()</span>:

3.12  TODO注释

对于下述情况使用<span style="font-size: 15px;">TODO</span>注释:临时的,短期的解决方案或者足够好但是不完美的解决方案.

<span style="font-size: 15px;">TODO</span>注释以全部大写的字符串<span style="font-size: 15px;">TODO</span>开头,并带有写入括号内的姓名,email地址,或其他可以标识负责人或者包含关于问题最佳描述的issue.随后是这里做什么的说明.

有统一风格的<span style="font-size: 15px;">TODO</span>的目的是为了方便搜索并了解如何获取更多相关细节.<span style="font-size: 15px;">TODO</span>并不是保证被提及者会修复问题.因此在创建<span style="font-size: 15px;">TODO</span>注释的时候,基本上都是给出你的名字.

如果<span style="font-size: 15px;">TODO</span>注释形式为"未来某个时间点会做什么事"的格式,确保要么给出一个非常具体的时间点(例如"将于2009年11月前修复")或者给出一个非常具体的事件(例如"当所有客户端都能够处理XML响应时就移除此代码").

3.13 import格式

imports应该在不同行.例如:

Yes:

No:

import应集中放在文件顶部,在模块注释和docstring后面,模块globals和常量前面.应按照从最通用到最不通用的顺序排列分组:

  1. Python未来版本import语句,例如:

    更多信息参看上文

  2. Python标准基础库import,例如:

  3. 第三方库或包的import,例如:

  4. 代码库内子包import,例如:

  5. 此条已弃用:和当前文件是同一顶级子包专用的import,例如:

    在旧版本的谷歌Python代码风格指南中实际上是这样做的.但是现在不再需要了.**新的代码风格不再受此困扰.**简单的将专用的子包import和其他子包import同一对待即可.

在每个组内按照每个模块的完整包路径的字典序忽略大小写排序.可以根据情况在每个节质检增加空行.

3.14 语句

每行只有一条语句.

不过如果测试语句和结果能够在一行内放下,就可以放在一行内.但是不允许将<span style="font-size: 15px;">try</span>/<span style="font-size: 15px;">except</span>语句和对应内容放于一行,因为<span style="font-size: 15px;">try</span>或者<span style="font-size: 15px;">except</span>都不能在一行内完成.对于没有else的if语句可以将<span style="font-size: 15px;">if</span>和对应内容合并到一行.

Yes:

No:

3.15 访问

对于琐碎又不太重要的访问函数,应用公共变量来替代访问函数,以避免额外的程序调用消耗,当添加了更多函数功能时,使用<span style="font-size: 15px;">property</span>来保持连续性

此外,如果访问过于复杂,或者访问变量的消耗过大,应该使用诸如<span style="font-size: 15px;">get_foo()</span><span style="font-size: 15px;">set_foo()</span>之类的函数式访问(参考命名指南).如果过去的访问方式是通过属性,新访问函数不要绑定到property上,这样使用property的旧方式就会失效,使用者就会知道函数有变化.

3.16 命名

<span style="font-size: 15px;color: rgb(0, 0, 0);">module_name</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">package_name</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">ClassName</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">method_name</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">ExceptionName</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">function_name</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">GLOBAL_CONSTANT_NAME</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">global_var_name</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">instance_var_name</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">function_parameter_name</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">local_var_name</span>.

命名函数名,变量名,文件名应该是描述性的,避免缩写,尤其避免模糊或对读者不熟悉的缩写.并且不要通过删减单词内的字母来缩短.

使用<span style="font-size: 15px;color: rgb(0, 0, 0);">.py</span>作为文件拓展名,不要使用横线.

3.16.1 要避免的名字:

  • 单字符名字,除非是计数或迭代元素,e可以作为Exception捕获识别名来使用..
  • <span style="font-size: 15px;color: rgb(0, 0, 0);">-</span>横线,不应出现在任何包名或模块名内
  • <span style="font-size: 15px;color: rgb(0, 0, 0);">__double_leading_and_trailing_underscore__</span>首尾都双下划线的名字,这种名字是python的内置保留名字

3.16.4 命名约定

  • internal表示仅模块内可用、或者类内保护的或者私有的
  • 单下划线(<span style="font-size: 15px;color: rgb(0, 0, 0);">_</span>)开头表示是被保护的(<span style="font-size: 15px;color: rgb(0, 0, 0);">from module import *</span>不会import).双下划线(<span style="font-size: 15px;color: rgb(0, 0, 0);">__</span>也就是"dunder")开头的实例变量或者方法表示类内私有(使用命名修饰).我们不鼓励使用,因为这会对可读性和可测试性有削弱二期<span style="font-size: 15px;color: rgb(0, 0, 0);">并非真正</span>的私有.
  • 相关的类和顶级函数放在同一个模块内,不必像是Java一样要一个类放在一个模块里.
  • 对类名使用大写字母(如CapWords)开头的单词,命名,模块名应该使用小写加下划线的方式.尽管有一些旧的模块命名方式是大写字母的(如CapWords.py),现在不鼓励这样做了,因为在模块刚好是从某个类命名出发的时候可能会令人迷惑(例如是选择<span style="font-size: 15px;color: rgb(0, 0, 0);">import StringIO</span>还是<span style="font-size: 15px;color: rgb(0, 0, 0);">from StringIO import StringIO</span>?)
  • unittest方法中可能是<span style="font-size: 15px;color: rgb(0, 0, 0);">test</span>开头来分割名字的组成部分,即使这些组成部分是使用大写字母驼峰式的.这种方式是可以的:<span style="font-size: 15px;color: rgb(0, 0, 0);">test<MethodUnderTest>_<state></span>例如<span style="font-size: 15px;color: rgb(0, 0, 0);">testPop_EmptyStack</span>,对于命名测试方法没有明确的正确方法.

3.16.3 文件名

文件拓展名必须为<span style="font-size: 15px;color: rgb(0, 0, 0);">.py</span>,不可以包含<span style="font-size: 15px;color: rgb(0, 0, 0);">-</span>.这保证了能够被正常import和单元测试.如果希望一个可执行文件不需要拓展名就可以被调用,那么建立一个软连接或者一个简单的bash打包脚本包括<span style="font-size: 15px;color: rgb(0, 0, 0);">exec "$0.py" "$@"</span>.

3.16.4 Guido的指导建议

类型 公共 内部
<span style="font-size: 15px;color: rgb(0, 0, 0);">lower_with_under</span>
模块 <span style="font-size: 15px;color: rgb(0, 0, 0);">lower_with_under</span> <span style="font-size: 15px;color: rgb(0, 0, 0);">_lower_with_under</span>
<span style="font-size: 15px;color: rgb(0, 0, 0);">CapWords</span> <span style="font-size: 15px;color: rgb(0, 0, 0);">_CapWords</span>
异常 <span style="font-size: 15px;color: rgb(0, 0, 0);">CapWords</span>
函数 <span style="font-size: 15px;color: rgb(0, 0, 0);">lower_with_under()</span> <span style="font-size: 15px;color: rgb(0, 0, 0);">_lower_with_under()</span>
全局/类常量 <span style="font-size: 15px;color: rgb(0, 0, 0);">CAPS_WITH_UNDER</span> <span style="font-size: 15px;color: rgb(0, 0, 0);">_CAPS_WITH_UNDER</span>
全局/类变量 <span style="font-size: 15px;color: rgb(0, 0, 0);">lower_with_under</span> <span style="font-size: 15px;color: rgb(0, 0, 0);">_lower_with_under</span>
实例变量 <span style="font-size: 15px;color: rgb(0, 0, 0);">lower_with_under</span> <span style="font-size: 15px;color: rgb(0, 0, 0);">_lower_with_under</span>(受保护)
方法名 <span style="font-size: 15px;color: rgb(0, 0, 0);">lower_with_under()</span> <span style="font-size: 15px;color: rgb(0, 0, 0);">_lower_with_under()</span>(受保护)
函数/方法参数 <span style="font-size: 15px;color: rgb(0, 0, 0);">lower_with_under</span>
局部变量 <span style="font-size: 15px;color: rgb(0, 0, 0);">lower_with_under</span>

尽管Python支持通过双下划线<span style="font-size: 15px;color: rgb(0, 0, 0);">__</span>(即"dunder")来私有化.不鼓励这样做.优先使用单下划线.单下划线更易于打出来、易读、易于小的单元测试调用.Lint的警告关注受保护成员的无效访问.

3.17 Main

即便是一个用做脚本的py文件也应该是可以被import的,而只用于import时,也不应有执行了主函数的副作用.主函数的功能应该被放在<span style="font-size: 15px;">main()</span>里.

在Python中,<span style="font-size: 15px;">pydoc</span>和单元测试要求模块是可import的.所以代码在主程序执行前应进行<span style="font-size: 15px;">if __name__ == '__main__':</span>检查,以防止模块在import时被执行.

所有顶级代码在模块被import时执行.因而要小心不要调用函数,创建对象或者执行其他在执行<span style="font-size: 15px;">pydoc</span>时不应该被执行的操作.

3.18 函数长度

优先写小而专一的函数.

长函数有时候是合适的,故而函数长度没有固定的限制.但是超过40行的时候就要考虑是否要在不影响程序结构的前提下分解函数.

尽管长函数现在运行的很好,但是在之后的时间里其他人修改函数并增加新功能的时候可能会引入新的难以发现的bug,保持函数的简短,这样有利于其他人读懂和修改代码.

在处理一些代码时,可能会发现有些函数长而且复杂.不要畏惧调整现有代码,如果处理这个函数非常困难,如难以对报错debug或者希望在几个不同的上下文中使用它,那么请将函数拆解成若干个更小更可控的片段.

3.19 类型注释

3.19.1 基本规则

  • 熟悉PEP-484
  • 在方法中,只在必要时给<span style="font-size: 15px;color: rgb(0, 0, 0);">self</span>或者<span style="font-size: 15px;color: rgb(0, 0, 0);">cls</span>增加合适的类型信息.例如<span style="font-size: 15px;color: rgb(0, 0, 0);">@classmethod def create(cls: Type[T]) -> T: return cls()</span>
  • 如果其他变量或返回类型不定,使用<span style="font-size: 15px;color: rgb(0, 0, 0);">Any</span>
  • 不需要注释每个函数
    • 至少需要注明公共接口
    • 使用类型检查来在安全性和声明清晰性以及灵活性之间平衡
    • 标注容易因类型相关而抛出异常的代码(previous bugs or complexity,此处译者认为是与上一条一致,平衡安全性和复杂性)
    • 标注难理解的代码
    • 标注类型稳定的代码,成熟稳定的代码可以都进行标注而不会影响其灵活性

3.19.2 分行

遵循现有的缩进规范

标注类型后,函数签名多数都要是"每行一个参数".

优先在变量之间换行,而非其他地方(如变量名和类型注释之间).如果都能放在一行内,就放在一行.

如果函数名,一直到最后的参数以及返回类型注释放在一行过长,那么分行并缩进4个空格.

当返回值类型不能和最后一个参数放入同一行,比较好的处理方式是将参数分行并缩进4个空格,右括号和返回值类型换行并和<span style="font-size: 15px;">def</span>对齐.

pylint允许您将右括号移动到新行并与左括号对齐,但这不太容易理解.

No:

就像上面的例子一样,尽量不要分割类型注释,不过有时类型注释太长无法放入一行,(那就尽量让子注释不要被分割).

如果某个命名和类型太长了,考虑使用别名.如果没有其他解决方案,在冒号后分行缩进4个空格.

Yes:

No:

3.19.3 前置声明

如果需要同一模块内还未定义的类名,例如需要类声明内部的类,或者需要在后续代码中定义的类,那么使用类名的字符串来代替.

3.19.4 默认值

参考PEP-008,只有在同时需要类型注释和默认值的时候在<span style="font-size: 15px;color: rgb(0, 0, 0);">=</span>前后都加空格

Yes:

No:

3.19.5 NoneType

在Python系统中<span style="font-size: 15px;color: rgb(0, 0, 0);">NoneType</span>是一等类型,为了方便输入,<span style="font-size: 15px;color: rgb(0, 0, 0);">None</span><span style="font-size: 15px;color: rgb(0, 0, 0);">NoneType</span>的别名.如果一个参数可以是<span style="font-size: 15px;color: rgb(0, 0, 0);">None</span>,那么就需要声明!可以使用<span style="font-size: 15px;color: rgb(0, 0, 0);">Union</span>,但如果只有一个其他类型,那么使用<span style="font-size: 15px;color: rgb(0, 0, 0);">Optional</span>.

显式地使用<span style="font-size: 15px;color: rgb(0, 0, 0);">Optional</span>而非隐式地.PEP 484的早期版本容许<span style="font-size: 15px;color: rgb(0, 0, 0);">a: Text = None</span>被解释为<span style="font-size: 15px;color: rgb(0, 0, 0);">a: Optional[Text] = None</span>.但现在已经不推荐这样使用了.

Yes:

No:

3.19.6 类型别名

可以对复杂类型声明别名,别名的名称应为CapWorded,如果只用于当前模块,应加下划线私有化.

例如,如果带有模块名的类型名过长:

其他示例是复杂的嵌套类型和一个函数的多个返回变量(作为元组).

3.19.7 忽略类型检查

可以通过增加特殊行注释<span style="font-size: 15px;color: rgb(0, 0, 0);"># type: ignore</span>来禁止类型检查.

<span style="font-size: 15px;color: rgb(0, 0, 0);">pytype</span>对于明确的报错有关闭选项(类似于lint):

3.19.8 对变量注释类型

对变量标注类型如果内部变量很难或者不可能指向,可以使用下述方式:

类型注释:

在行尾增加以<span style="font-size: 15px;color: rgb(0, 0, 0);"># type</span>开头的注释

注释绑定:

在变量名和赋值之间用冒号和类型注明,和函数参数一致.

3.19.9 元组和列表

不像是列表只能包含单一类型,元组可以既只有一种重复类型或者一组不同类型的元素,后者常用于函数返回.

3.19.10 TypeVars

Python是有泛型的,工厂函数<span style="font-size: 15px;color: rgb(0, 0, 0);">TypeVar</span>是通用的使用方式.

例子:

TypeVar可以约束类型:

<span style="font-size: 15px;">typing</span>模块预定义好的类型变量是<span style="font-size: 15px;">AnyStr</span>,用于针对字符串可以是<span style="font-size: 15px;">bytes</span>也可为<span style="font-size: 15px;">unicode</span>并且保持一致的多个类型注释.

3.19.11 字符串类型

注释字符串的合适类型是基于Python版本的.

对于只有Python3的代码,使用<span style="font-size: 15px;color: rgb(0, 0, 0);">str</span>,<span style="font-size: 15px;color: rgb(0, 0, 0);">Text</span>可以用但是在选择上保持一致.

对于Python2兼容的代码,用<span style="font-size: 15px;color: rgb(0, 0, 0);">Text</span>,在一些很罕见的情况下,<span style="font-size: 15px;color: rgb(0, 0, 0);">str</span>可能可用.当在不同Python版本之间返回值类型不同的时候通常是为了照顾兼容性.避免使用<span style="font-size: 15px;color: rgb(0, 0, 0);">unicode</span>,因为Python3中不存在.

No:

对于处理二进制数据的代码,请使用<span style="font-size: 15px;">bytes</span>.

Yes:

对于Python2兼容,处理文本数据(Python中<span style="font-size: 15px;">str</span><span style="font-size: 15px;">unicode</span>,Python3中<span style="font-size: 15px;">str</span>)的代码,使用<span style="font-size: 15px;">Text</span>.对于只有Python3的代码,优先使用<span style="font-size: 15px;">str</span>.

如果既可以是byte也可以是文本,那么使用<span style="font-size: 15px;">Union</span>和合适的文本类型.

如果一个函数中所有的字符串类型始终一致,例如前文例子中返回值类型和参数类型是一致的,那么使用<span style="font-size: 15px;color: rgb(0, 0, 0);">AnyStr</span>

像这样写能够简化代码向Python3的迁移过程.

3.19.12 typing的import

对于从<span style="font-size: 15px;color: rgb(0, 0, 0);">typing</span>模块import的类,要import类本身.明确的允许在一行内从<span style="font-size: 15px;color: rgb(0, 0, 0);">typing</span>模块import多个特定的类,如

这种从<span style="font-size: 15px;">typing</span>模块import的方式会向命名空间内增加额外项,<span style="font-size: 15px;">typing</span>中的任何命名都应该和关键字同等对待并且不在你的Python代码中定义,typed or not(译者推测文无论是否引入).如果和已有的命名冲突,使用<span style="font-size: 15px;">import x as y</span>来import.

3.19.13 条件import

只在运行时一定要避免进行类型检查的情况下使用条件import.不鼓励使用这种模式.鼓励使用其他替代方式诸如重构代码以容许顶级import.

只用于类型注释的import可以被归于<span style="color: rgb(0, 0, 0);font-size: 15px;">if TYPE_CHECKING:</span>代码块中.

  • 条件import的类型应被视为字符串引用,以和Python3.6兼容(在Python3.6中,注释表达式实际上被赋值的).
  • 只有单独用于类型注释的实例才能在这里定义,包括了别名.否则将会报运行错误因为在运行时这些模块不会被引用.
  • 代码块应该紧跟在正常import后面.
  • 在类型import后不应有空行
  • 按照正常import顺序对这一块代码进行排序

3.19.14 循环依赖

由于类型检查引发的循环依赖是一种code smell(代码异味),这样的代码应当被重构.尽管技术上是可以保留循环引用的.build system(系统)不允许这样做因为每个模块都要依赖于其他模块.

将造成循环依赖的模块替换为<span style="font-size: 15px;color: rgb(0, 0, 0);">Any</span>并赋予一个有意义的别名并使用从这个模块导入的真实类名(因为任何<span style="font-size: 15px;color: rgb(0, 0, 0);">Any</span>的属性都是<span style="font-size: 15px;color: rgb(0, 0, 0);">Any</span>).别名的定义用和最后一行import用一行空行分隔.

3.19.15  泛型

当注释的时候,优先泛型类型专有类型参数,否则泛型的参数会被认为是<span style="font-size: 15px;color: rgb(0, 0, 0);">Any</span>.

如果泛型最佳的参数类型是<span style="font-size: 15px;">Any</span>也将其显式地表示出来.但是在很多情况下<span style="font-size: 15px;">TypeVar</span>可能更合适.

4、最后的话

如果你在编辑代码,花几分钟看看现有代码然后决定好要使用哪种风格.如果现有代码在所有算术运算符两侧都加了空格,那么你也应该如此.如果现有的注释用井号组成了包围框,那么你的注释也应如此.

有代码风格指南的目的是有一个编程的共识,这样人们能够集中在内容而非形式上.我们将通用的代码风格指南公布于此这样人们就能了解这个共识(译者:有巴别塔的意味.)但是各自的代码风格也很重要.如果你添加的代码与原有代码看起来完全不一致,就会打乱读者的阅读节奏,避免这样。


<p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="__bg_gif" data-ratio="0.08658008658008658"  data-type="gif" data-w="462" data-width="100%" style="color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 578px !important;" src="https://www.zkxjob.com/wp-content/uploads/2022/07/wxsync-2022-07-ae45c8833e6e59cceba3c2fda2df37d1.gif"  /></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"  /></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;color: rgb(2, 30, 170);box-sizing: border-box !important;overflow-wrap: break-word !important;">推荐阅读:</span></strong></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;color: rgb(2, 30, 170);box-sizing: border-box !important;overflow-wrap: break-word !important;">入门: </span><span style="max-width: 100%;color: rgb(2, 30, 170);text-decoration: underline;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">最全的零基础学Python的问题</span><span style="max-width: 100%;font-size: 15px;color: rgb(2, 30, 170);box-sizing: border-box !important;overflow-wrap: break-word !important;">  | </span><span style="max-width: 100%;color: rgb(2, 30, 170);text-decoration: underline;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">零基础学了8个月的Python </span> <span style="max-width: 100%;color: rgb(2, 30, 170);text-decoration: underline;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">|</span> <span style="max-width: 100%;text-decoration: underline;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">实战项目</span> <span style="max-width: 100%;text-decoration: underline;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">|学Python就是这条捷径</span></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"  /></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;color: rgb(2, 30, 170);box-sizing: border-box !important;overflow-wrap: break-word !important;">干货:</span><span style="max-width: 100%;font-size: 15px;color: rgb(2, 30, 170);text-decoration: underline;box-sizing: border-box !important;overflow-wrap: break-word !important;">爬取豆瓣短评,电影《后来的我们》</span> | <span style="max-width: 100%;font-size: 14px;text-decoration: underline;box-sizing: border-box !important;overflow-wrap: break-word !important;">38年NBA最佳球员分析 </span><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;text-decoration: underline;box-sizing: border-box !important;overflow-wrap: break-word !important;">|</span>   </span><span style="max-width: 100%;font-size: 15px;text-decoration: underline;box-sizing: border-box !important;overflow-wrap: break-word !important;">从万众期待到口碑扑街!唐探3令人失望</span>  | 笑看新倚天屠龙记 | 灯谜答题王 |<span style="max-width: 100%;font-size: 14px;text-decoration: underline;box-sizing: border-box !important;overflow-wrap: break-word !important;">用Python做个海量小姐姐素描图 |</span></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"  /></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;color: rgb(2, 30, 170);box-sizing: border-box !important;overflow-wrap: break-word !important;">趣味:</span><span style="max-width: 100%;color: rgb(2, 30, 170);text-decoration: underline;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">弹球游戏</span>  | <span style="max-width: 100%;text-decoration: underline;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">九宫格</span>  | 漂亮的花 | 两百行Python《天天酷跑》游戏!</p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"  /></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(2, 30, 170);box-sizing: border-box !important;overflow-wrap: break-word !important;">AI:</span> 会做诗的机器人 | 给图片上色 | 预测收入 | 碟中谍这么火,我用机器学习做个迷你推荐系统电影</p>


年度爆款文案

  • 1).卧槽!Pdf转Word用Python轻松搞定

  • 2).学Python真香!我用100行代码做了个网站,帮人PS旅行图片,赚个鸡腿吃

  • 3).首播过亿,火爆全网,我分析了《乘风破浪的姐姐》,发现了这些秘密 

  • 4).80行代码!用Python做一个哆来A梦分身 

  • 5).你必须掌握的20个python代码,短小精悍,用处无穷 

  • 6).30个Python奇淫技巧集 

  • 7).我总结的80页《菜鸟学Python精选干货.pdf》,都是干货 

  • 8).再见Python!我要学Go了!2500字深度分析!

  • 9).发现一个舔狗福利!这个Python爬虫神器太爽了,自动下载妹子图片


<section data-mpa-template="t" mpa-from-tpl="t" data-darkmode-bgcolor-15923650965579="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15923650965579="rgb(255, 255, 255)" data-darkmode-color-15923650965579="rgb(168, 168, 168)" data-darkmode-original-color-15923650965579="rgb(62, 62, 62)" data-style="color: rgb(62, 62, 62); font-size: 15px; letter-spacing: 0.544px; background-color: rgb(255, 255, 255); font-family: monospace; text-align: left; widows: 1; word-spacing: 2px; caret-color: rgb(255, 0, 0); white-space: pre-wrap;" style="max-width: 100%;font-size: 15px;letter-spacing: 0.544px;word-spacing: 2px;caret-color: rgb(255, 0, 0);color: rgb(62, 62, 62);white-space: pre-wrap;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section mpa-from-tpl="t" data-darkmode-bgcolor-15923650965579="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15923650965579="rgb(255, 255, 255)" data-darkmode-color-15923650965579="rgb(168, 168, 168)" data-darkmode-original-color-15923650965579="rgb(62, 62, 62)" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><pre data-darkmode-bgcolor-15923650965579="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15923650965579="rgb(255, 255, 255)" data-darkmode-color-15923650965579="rgb(167, 167, 167)" data-darkmode-original-color-15923650965579="rgb(63, 63, 63)" data-style="letter-spacing: 0.544px; font-size: 16px; color: rgb(63, 63, 63); word-spacing: 1px; line-height: inherit;" style="max-width: 100%;letter-spacing: 0.544px;font-size: 16px;color: rgb(63, 63, 63);word-spacing: 1px;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-mpa-template-id="1250" data-mpa-color="#ffffff" data-mpa-category="divider" data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(230, 230, 230)" data-darkmode-original-color="rgb(0, 0, 0)" data-style="margin-right: 0.5em; margin-left: 0.5em; white-space: normal; font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; color: rgb(0, 0, 0); letter-spacing: 0px; word-spacing: 2px;" data-darkmode-bgcolor-15923650965579="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15923650965579="rgb(255, 255, 255)" data-darkmode-color-15923650965579="rgb(230, 230, 230)" data-darkmode-original-color-15923650965579="rgb(0, 0, 0)" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><pre data-darkmode-bgcolor-15923650965579="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15923650965579="rgb(255, 255, 255)" data-darkmode-color-15923650965579="rgb(167, 167, 167)" data-darkmode-original-color-15923650965579="rgb(63, 63, 63)" data-style="letter-spacing: 0.544px; font-size: 16px; color: rgb(63, 63, 63); word-spacing: 1px; line-height: inherit;" style="max-width: 100%;letter-spacing: 0.544px;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-mpa-template-id="1250" data-mpa-color="#ffffff" data-mpa-category="divider" data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(230, 230, 230)" data-darkmode-original-color="rgb(0, 0, 0)" data-style="margin-right: 0.5em; margin-left: 0.5em; white-space: normal; font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; color: rgb(0, 0, 0); letter-spacing: 0px; word-spacing: 2px;" data-darkmode-bgcolor-15923650965579="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15923650965579="rgb(255, 255, 255)" data-darkmode-color-15923650965579="rgb(230, 230, 230)" data-darkmode-original-color-15923650965579="rgb(0, 0, 0)" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section powered-by="xiumi.us" data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(230, 230, 230)" data-darkmode-original-color="rgb(0, 0, 0)" data-darkmode-bgcolor-15923650965579="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15923650965579="rgb(255, 255, 255)" data-darkmode-color-15923650965579="rgb(230, 230, 230)" data-darkmode-original-color-15923650965579="rgb(0, 0, 0)" style="margin-right: 0em;margin-left: 0em;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section style="margin-right: 0.5em;margin-left: 0.5em;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><pre data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(168, 168, 168)" data-darkmode-original-color="rgb(62, 62, 62)" data-style="letter-spacing: 0.544px; font-weight: 700; text-align: -webkit-center; background-color: rgb(255, 255, 255); font-size: 16px; color: rgb(62, 62, 62); widows: 1; word-spacing: 2px;" style="max-width: 100%;letter-spacing: 0.544px;text-align: center;text-size-adjust: auto;color: rgb(62, 62, 62);font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><pre data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(168, 168, 168)" data-darkmode-original-color="rgb(62, 62, 62)" data-style="letter-spacing: 0.544px; font-weight: 700; text-align: -webkit-center; background-color: rgb(255, 255, 255); font-size: 16px; color: rgb(62, 62, 62); widows: 1; word-spacing: 2px;" style="max-width: 100%;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><pre style="max-width: 100%;letter-spacing: 0.544px;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><h1 style="max-width: 100%;white-space: pre-wrap;letter-spacing: 0.544px;font-family: 微软雅黑;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><pre style="max-width: 100%;letter-spacing: 0.544px;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-mpa-template="t" mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-id="94086" data-color="#276ca3" data-tools="135编辑器" mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><pre style="max-width: 100%;color: rgb(63, 63, 63);letter-spacing: 0.544px;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-mpa-template="t" mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-id="94086" data-color="#276ca3" data-tools="135编辑器" mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section mpa-from-tpl="t" style="max-width: 100%;display: inline-block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><pre style="max-width: 100%;letter-spacing: 0.544px;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><pre data-darkmode-bgcolor-15882384789136="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882384789136="rgb(255, 255, 255)" data-style="letter-spacing: 0.544px; background-color: rgb(255, 255, 255); text-align: center; color: rgba(230, 230, 230, 0.9); font-size: 16px; line-height: 25.6px; overflow-wrap: break-word !important;" data-darkmode-bgcolor-15882396318564="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882396318564="rgb(255, 255, 255)" data-darkmode-color-15882396318564="rgba(230, 230, 230, 0.9)" data-darkmode-original-color-15882396318564="rgba(230, 230, 230, 0.9)" data-darkmode-bgcolor-15900529136199="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15900529136199="rgb(255, 255, 255)" data-darkmode-color-15900529136199="rgba(230, 230, 230, 0.9)" data-darkmode-original-color-15900529136199="rgba(230, 230, 230, 0.9)" style="max-width: 100%;letter-spacing: 0.544px;text-align: center;color: rgba(230, 230, 230, 0.9);line-height: 25.6px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-darkmode-bgcolor-15860613985508="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15860613985508="rgb(255, 255, 255)" data-darkmode-color-15860613985508="rgb(230, 230, 230)" data-darkmode-original-color-15860613985508="rgb(0, 0, 0)" data-darkmode-bgcolor-15870356070738="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356070738="rgb(255, 255, 255)" data-darkmode-color-15870356070738="rgb(230, 230, 230)" data-darkmode-original-color-15870356070738="rgb(0, 0, 0)" data-darkmode-bgcolor-15870356071023="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356071023="rgb(255, 255, 255)" data-darkmode-color-15870356071023="rgb(230, 230, 230)" data-darkmode-original-color-15870356071023="rgb(0, 0, 0)" data-darkmode-bgcolor-15882384789136="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882384789136="rgb(255, 255, 255)" data-darkmode-color-15882384789136="rgb(230, 230, 230)" data-darkmode-original-color-15882384789136="rgb(0, 0, 0)" data-darkmode-bgcolor-15882396318564="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882396318564="rgb(255, 255, 255)" data-darkmode-color-15882396318564="rgb(230, 230, 230)" data-darkmode-original-color-15882396318564="rgb(0, 0, 0)" data-darkmode-bgcolor-15900529136199="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15900529136199="rgb(255, 255, 255)" data-darkmode-color-15900529136199="rgb(230, 230, 230)" data-darkmode-original-color-15900529136199="rgb(0, 0, 0)" style="max-width: 100%;display: inline-block;clear: both;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-tools="135编辑器" data-id="91842" data-darkmode-bgcolor-15860613985508="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15860613985508="rgb(255, 255, 255)" data-darkmode-color-15860613985508="rgb(230, 230, 230)" data-darkmode-original-color-15860613985508="rgb(0, 0, 0)" data-darkmode-bgcolor-15870356070738="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356070738="rgb(255, 255, 255)" data-darkmode-color-15870356070738="rgb(230, 230, 230)" data-darkmode-original-color-15870356070738="rgb(0, 0, 0)" data-darkmode-bgcolor-15870356071023="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356071023="rgb(255, 255, 255)" data-darkmode-color-15870356071023="rgb(230, 230, 230)" data-darkmode-original-color-15870356071023="rgb(0, 0, 0)" data-darkmode-bgcolor-15882384789136="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882384789136="rgb(255, 255, 255)" data-darkmode-color-15882384789136="rgb(230, 230, 230)" data-darkmode-original-color-15882384789136="rgb(0, 0, 0)" data-darkmode-bgcolor-15882396318564="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882396318564="rgb(255, 255, 255)" data-darkmode-color-15882396318564="rgb(230, 230, 230)" data-darkmode-original-color-15882396318564="rgb(0, 0, 0)" data-darkmode-bgcolor-15900529136199="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15900529136199="rgb(255, 255, 255)" data-darkmode-color-15900529136199="rgb(230, 230, 230)" data-darkmode-original-color-15900529136199="rgb(0, 0, 0)" style="max-width: 100%;letter-spacing: 0.544px;border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-darkmode-bgcolor-15860613985508="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15860613985508="rgb(255, 255, 255)" data-darkmode-color-15860613985508="rgb(230, 230, 230)" data-darkmode-original-color-15860613985508="rgb(0, 0, 0)" data-darkmode-bgcolor-15870356070738="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356070738="rgb(255, 255, 255)" data-darkmode-color-15870356070738="rgb(230, 230, 230)" data-darkmode-original-color-15870356070738="rgb(0, 0, 0)" data-darkmode-bgcolor-15870356071023="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356071023="rgb(255, 255, 255)" data-darkmode-color-15870356071023="rgb(230, 230, 230)" data-darkmode-original-color-15870356071023="rgb(0, 0, 0)" data-darkmode-bgcolor-15882384789136="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882384789136="rgb(255, 255, 255)" data-darkmode-color-15882384789136="rgb(230, 230, 230)" data-darkmode-original-color-15882384789136="rgb(0, 0, 0)" data-darkmode-bgcolor-15882396318564="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882396318564="rgb(255, 255, 255)" data-darkmode-color-15882396318564="rgb(230, 230, 230)" data-darkmode-original-color-15882396318564="rgb(0, 0, 0)" data-darkmode-bgcolor-15900529136199="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15900529136199="rgb(255, 255, 255)" data-darkmode-color-15900529136199="rgb(230, 230, 230)" data-darkmode-original-color-15900529136199="rgb(0, 0, 0)" style="max-width: 100%;display: inline-block;clear: both;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-brushtype="text" data-darkmode-bgcolor-15860613985508="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15860613985508="rgb(255, 255, 255)" data-darkmode-color-15860613985508="rgb(230, 230, 230)" data-darkmode-original-color-15860613985508="rgb(0, 0, 0)" data-darkmode-bgimage-15860613985508="1" data-style="padding: 18px 15px 20px 10px; color: rgb(86, 146, 214); text-align: center; letter-spacing: 1.5px; background-image: url('https://www.zkxjob.com/wp-content/uploads/2022/07/wxsync-2022-07-a2a8a5e1e58f30392066a170034ee027.png'); background-size: 100% 100%; background-repeat: no-repeat; overflow-wrap: break-word !important;" data-darkmode-bgcolor-15870356070738="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356070738="rgb(255, 255, 255)" data-darkmode-color-15870356070738="rgb(230, 230, 230)" data-darkmode-original-color-15870356070738="rgb(0, 0, 0)" data-darkmode-bgimage-15870356070738="1" data-darkmode-bgcolor-15870356071023="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356071023="rgb(255, 255, 255)" data-darkmode-color-15870356071023="rgb(230, 230, 230)" data-darkmode-original-color-15870356071023="rgb(0, 0, 0)" data-darkmode-bgimage-15870356071023="1" data-darkmode-bgcolor-15882384789136="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882384789136="rgb(255, 255, 255)" data-darkmode-color-15882384789136="rgb(230, 230, 230)" data-darkmode-original-color-15882384789136="rgb(0, 0, 0)" data-darkmode-bgimage-15882384789136="1" data-darkmode-bgcolor-15882396318564="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882396318564="rgb(255, 255, 255)" data-darkmode-color-15882396318564="rgb(230, 230, 230)" data-darkmode-original-color-15882396318564="rgb(0, 0, 0)" data-darkmode-bgimage-15882396318564="1" data-darkmode-bgcolor-15900529136199="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15900529136199="rgb(255, 255, 255)" data-darkmode-color-15900529136199="rgb(230, 230, 230)" data-darkmode-original-color-15900529136199="rgb(0, 0, 0)" data-darkmode-bgimage-15900529136199="1" style="padding: 18px 15px 20px 10px;max-width: 100%;background-size: 100% 100%;background-image: url('https://www.zkxjob.com/wp-content/uploads/2022/07/wxsync-2022-07-a2a8a5e1e58f30392066a170034ee027.png');color: rgb(86, 146, 214);letter-spacing: 1.5px;background-repeat: no-repeat;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-darkmode-bgcolor-15860613985508="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15860613985508="rgb(255, 255, 255)" data-darkmode-color-15860613985508="rgb(230, 230, 230)" data-darkmode-original-color-15860613985508="rgb(0, 0, 0)" data-darkmode-bgimage-15860613985508="1" data-darkmode-bgcolor-15870356070738="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356070738="rgb(255, 255, 255)" data-darkmode-color-15870356070738="rgb(230, 230, 230)" data-darkmode-original-color-15870356070738="rgb(0, 0, 0)" data-darkmode-bgimage-15870356070738="1" data-darkmode-bgcolor-15870356071023="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356071023="rgb(255, 255, 255)" data-darkmode-color-15870356071023="rgb(230, 230, 230)" data-darkmode-original-color-15870356071023="rgb(0, 0, 0)" data-darkmode-bgimage-15870356071023="1" data-darkmode-bgcolor-15882384789136="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882384789136="rgb(255, 255, 255)" data-darkmode-color-15882384789136="rgb(230, 230, 230)" data-darkmode-original-color-15882384789136="rgb(0, 0, 0)" data-darkmode-bgimage-15882384789136="1" data-darkmode-bgcolor-15882396318564="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882396318564="rgb(255, 255, 255)" data-darkmode-color-15882396318564="rgb(230, 230, 230)" data-darkmode-original-color-15882396318564="rgb(0, 0, 0)" data-darkmode-bgimage-15882396318564="1" data-darkmode-bgcolor-15900529136199="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15900529136199="rgb(255, 255, 255)" data-darkmode-color-15900529136199="rgb(230, 230, 230)" data-darkmode-original-color-15900529136199="rgb(0, 0, 0)" data-darkmode-bgimage-15900529136199="1" style="max-width: 100%;display: flex;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><section data-darkmode-bgcolor-15860613985508="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15860613985508="rgb(255, 255, 255)" data-darkmode-color-15860613985508="rgb(230, 230, 230)" data-darkmode-original-color-15860613985508="rgb(0, 0, 0)" data-darkmode-bgimage-15860613985508="1" data-darkmode-bgcolor-15870356070738="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356070738="rgb(255, 255, 255)" data-darkmode-color-15870356070738="rgb(230, 230, 230)" data-darkmode-original-color-15870356070738="rgb(0, 0, 0)" data-darkmode-bgimage-15870356070738="1" data-darkmode-bgcolor-15870356071023="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356071023="rgb(255, 255, 255)" data-darkmode-color-15870356071023="rgb(230, 230, 230)" data-darkmode-original-color-15870356071023="rgb(0, 0, 0)" data-darkmode-bgimage-15870356071023="1" data-darkmode-bgcolor-15882384789136="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882384789136="rgb(255, 255, 255)" data-darkmode-color-15882384789136="rgb(230, 230, 230)" data-darkmode-original-color-15882384789136="rgb(0, 0, 0)" data-darkmode-bgimage-15882384789136="1" data-darkmode-bgcolor-15882396318564="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882396318564="rgb(255, 255, 255)" data-darkmode-color-15882396318564="rgb(230, 230, 230)" data-darkmode-original-color-15882396318564="rgb(0, 0, 0)" data-darkmode-bgimage-15882396318564="1" data-darkmode-bgcolor-15900529136199="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15900529136199="rgb(255, 255, 255)" data-darkmode-color-15900529136199="rgb(230, 230, 230)" data-darkmode-original-color-15900529136199="rgb(0, 0, 0)" data-darkmode-bgimage-15900529136199="1" style="margin-left: 2px;max-width: 100%;width: 20px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></section><section data-brushtype="text" data-darkmode-bgcolor-15860613985508="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15860613985508="rgb(255, 255, 255)" data-darkmode-color-15860613985508="rgb(51, 51, 51)" data-darkmode-original-color-15860613985508="rgb(51, 51, 51)" data-darkmode-bgimage-15860613985508="1" data-darkmode-bgcolor-15870356070738="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356070738="rgb(255, 255, 255)" data-darkmode-color-15870356070738="rgb(51, 51, 51)" data-darkmode-original-color-15870356070738="rgb(51, 51, 51)" data-darkmode-bgimage-15870356070738="1" data-darkmode-bgcolor-15870356071023="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15870356071023="rgb(255, 255, 255)" data-darkmode-color-15870356071023="rgb(51, 51, 51)" data-darkmode-original-color-15870356071023="rgb(51, 51, 51)" data-darkmode-bgimage-15870356071023="1" data-darkmode-bgcolor-15882384789136="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882384789136="rgb(255, 255, 255)" data-darkmode-color-15882384789136="rgb(51, 51, 51)" data-darkmode-original-color-15882384789136="rgb(51, 51, 51)" data-darkmode-bgimage-15882384789136="1" data-darkmode-bgcolor-15882396318564="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15882396318564="rgb(255, 255, 255)" data-darkmode-color-15882396318564="rgb(51, 51, 51)" data-darkmode-original-color-15882396318564="rgb(51, 51, 51)" data-darkmode-bgimage-15882396318564="1" data-darkmode-bgcolor-15900529136199="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15900529136199="rgb(255, 255, 255)" data-darkmode-color-15900529136199="rgb(51, 51, 51)" data-darkmode-original-color-15900529136199="rgb(51, 51, 51)" data-darkmode-bgimage-15900529136199="1" style="max-width: 100%;font-size: 14px;color: rgb(51, 51, 51);text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-family: 楷体, 楷体_GB2312, SimKai;white-space: pre-wrap;font-size: 12px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点阅读原文,领廖雪峰视频资料!</span><span style="background-color: rgb(239, 239, 239);color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;letter-spacing: 0.544px;word-spacing: 2px;"></span></section></section></section></section></section></section></section>

本篇文章来源于: 菜鸟学Python

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

知行编程网
知行编程网 关注:1    粉丝:1
这个人很懒,什么都没写

你可能也喜欢

热评文章

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享