• Python是一种对代码风格很强调的言语,从缩进就能见到这或多或少,Python强调易于精通。如今在负责代码重构的工作,为了统一咱们的代码风格,制订规范,学习了一下网上这份Google的Python风格指南。

  • 原稿地址:
    http://google-styleguide.googlecode.com/svn/trunk/pyguide.html

尼采

背景

Python 是
Google重要的脚本语言。这本风格指南重要包含的是本着python的编程准则。
为扶持读者可以将代码准确格式化,我们提供了针对 Vim的布置文件
。对于Emacs用户,保持默认设置即可。

李笑来老师倡议了“十分钟读完一本好书”活动,最初的灵感是:

Python语言专业

假设有人把一本书的出色提取出来,十分钟给自身讲完,我应当给她钱的,而且这钱数一定应该比这本书的定价高出许多倍,因为他帮自己省了时间……

pylint

Tip
对您的代码运行pylint

定义:
pylint是一个在Python源代码中查找bug的工具.
对于C和C++这样的不那么动态的(译者注: 原文是less dynamic)语言,
这多少个bug平时由编译器来捕获. 由于Python的动态特性, 有些警告或者不对.
然则伪告警应该很少.
优点:
可以捕获容易忽略的荒唐, 例如输入错误, 使用未赋值的变量等.
缺点:
pylint不完美. 要采用其优势, 我们偶尔侯需要: a) 围绕着它来写代码 b)
抑制其报警 c) 立异它, 或者d) 忽略它.
结论:
保证对你的代码运行pylint.抑制不可靠的警示,以便可以将另外警告透表露来。
你可以透过安装一个行注释来压制告警. 例如:

dict = 'something awful'  # Bad Idea... pylint: disable=redefined-builtin

pylint警告是以一个数字编号(如 C0112 )和一个标记名(如 empty-docstring
)来标识的. 在编制新代码或更新已有代码时对报警进行医疗,
推荐使用标志名来标识.

比方警告的标志名不够见名知意,那么请对其扩大一个详尽分解。

利用这种抑制情势的便宜是大家得以轻松查找抑制并记念它们.

您可以行使命令 pylint --list-msgs 来获取pylint告警列表. 你可以选取命令
pylint --help-msg=C6409 , 以博得有关特定音信的更多新闻.

相比较于事先使用的 pylint: disable-msg , 本文推荐使用
pylint: disable .

要遏制”参数未使用”告警, 你能够用””作为参数标识符,
或者在参数名前加”unused
”. 境遇不可能更改参数名的状况,
你可以通过在函数起头”提到”它们来清除告警. 例如:

    def foo(a, unused_b, unused_c, d=None, e=None):
        _ = d, e
        return a

这的确是个好主意,就借此机会,系统回顾一下本人读过的书呢。一方面是给大家介绍一些团结喜爱的书,一方面也是振奋自己阅读与探究

导入

Tip
仅对包和模块使用导入

定义:
模块间共享代码的选定机制.
优点:
取名空间管理约定非常简单. 每个标识符的源都用一种同等的办法指示.
x.Obj表示Obj对象定义在模块x中.
科学,缺点:
模块名仍可能争辨. 有些模块名太长, 不太方便.
结论:
使用 import x 来导入包和模块.

使用 from x import y , 其中x是包前缀, y是不带前缀的模块名.

使用 from x import y as z, 假设多少个要导入的模块都叫做z或者y太长了.

例如, 模块 sound.effects.echo 可以用如下格局导入:

    from sound.effects import echo
    ...
    echo.EchoFilter(input, output, delay=0.7, atten=4)

导入时决不采取相对名称. 固然模块在同一个包中, 也要选用完整包名.
这能支援您避免无意间导入一个包五回.

引言

首先次接触尼采的书是在高考结束后的暑假,读过《作为国学家的叔本华》和《查拉图斯特拉(Stella)如是说》,没有感受到稍微乐趣,也没怎么读懂。本科的时候,又有三遍尝试过读《查拉图丝特拉如是说》,可是都未曾读完过。总是觉得这本书太丰硕、太博大精深了,就像爬一座高山,总没有丰裕的劲头爬到山上。直到很晚,我才精通,这样的书是内需渐渐读的,我平素都是太过着急了。

大学生一年级的时候,我偶然间在教室发现了刘小枫主编的《尼采注疏集》,一下子就喜好上了,把能找到的都借了回来(《人性的、太人性的》《快乐的不错》《朝霞》《偶像的黄昏》《重估一切价值》)。之后的挺长期,我都在看这套书,做了汪洋的摘要(这么些挺花时间的)。后来,我集齐了那套书,不过,看得更多的依然从前的那多少个笔记。

在我看来,尼采的创作是不可能缩写的。我只是尝试从笔记中找一些最喜爱的情节分享给我们。希望可以引起你们对尼采的兴趣。

《人性的、太人性的:一本献给自由精神的书(下卷)》

作者:尼采

译者: 魏育青 / 李晶浩 / 高天忻

出版社:华东政法大学出版社

ISBN:9787561757635

版次:2008年4月

丛书: 西方传统:经典与解释·尼采注疏集

Tip
使用模块的全方位径名来导入每个模块

优点:
制止模块名顶牛. 查找包更容易.
缺点:
布置代码变难, 因为您不可能不复制包层次.
结论:
拥有的新代码都应有用一体化包名来导入每个模块.

应当像上面这样导入:

# Reference in code with complete name.
import sound.effects.echo

# Reference in code with just module name (preferred).
from sound.effects import echo

作者简介

尼采(1844年十月15日—1900年五月25日)德意志联邦共和国知名翻译家,被认为是西方现代农学的创制者,语言学家、文化评论家、作家、作曲家、思想家,他的创作对于宗教、道德、现代文化、艺术学、以及科学等领域指出了常见的批判和商量。他的行文风格独特,平日利用准则和悖论的技巧。尼采对于后人军事学的提升影响极大,尤其是在存在主义与后现代主义上。

在开头研商法学前,尼采是一名文字学家。24岁时尼采成为了瑞士联邦海牙高校的爱沙尼亚语区古典语教育学教书,专攻古芬兰语,拉丁文文献。但在1879年是因为健康问题而辞职,之后直接备受精神疾病煎熬。1889年尼采精神崩溃,从此再也未曾过来,在大妈和四姐的照应下直接活到1900年寿终正寝。(摘自百度健全)

异常

Tip
同意行使分外, 但必须小心

定义:
老大是一种跳出代码块的正规控制流来处理错误或者另外非凡条件的模式.
优点:
正常操作代码的控制流不会和错误处理代码混在一起. 当某种条件暴发时,
它也允许控制流跳过四个框架. 例如, 一步跳出N个嵌套的函数,
而不必继续执行错误的代码.
缺点:
兴许会促成令人纳闷的主宰流. 调用库时便于失去错误情况.
结论:
可怜必须信守特定条件:

  1. 像这么触发分外: raise MyException("Error message") 或者
    raise MyException . 不要选用多少个参数的款式(
    raise MyException, "Error message" )或者过时的字符串极度(
    raise "Error message" ).

  2. 模块或包应该定义自己的特定域的充足基类,
    这个基类应该从内建的Exception类继承. 模块的老大基类应该称为”Error”.

    class Error(Exception):
        pass
  1. 世代不要采用 except: 语句来捕获所有特别, 也毫不捕获 Exception
    或者 StandardError , 除非你打算重新触发该特别,
    或者你已经在眼前线程的最外层(记得仍然要打印一条错误音信).
    在充足这上头, Python十分宽容, except:
    真的会捕获包括Python语法错误在内的别样错误. 使用 except:
    很容易隐藏真正的bug.

  2. 尽量减弱try/except块中的代码量. try块的体积越大,
    期望之外的不得了就越容易被触发. 这种状态下,
    try/except块将躲藏真正的错误.

  3. 选取finally子句来施行这个无论try块中有没有十分都应有被实践的代码.
    这对于清理资源通常很有用, 例如关闭文件.
    当捕获非凡时, 使用 as 而毫无用逗号. 例如

try:
    raise Error
except Error as error:
    pass

忙乱的见识和题词

77

纵欲——纵欲并非来自快乐,而是源于苦闷

82

精晓洗净自己——不可以不学会出淤泥而不染,万不得已时用污水洗净自己

107

四分之三的马力——一部著作要想给人留下健康的记念,那么创作者至多可以用四分之三的马力。假使她不这样做,反而倾尽全力,那么该小说就会因其张力而使观看者陷入不安和恐怖。抱有美好事物都带着几分倦慵,宛若躺在草地上的奶牛。

113

最轻易的大手笔——一本献给自由精神的书怎么能不关乎劳伦斯•斯特恩,不关乎这一个被歌德奉为他万分世纪里最具自由精神的人。但愿他在此能将就着接受这一荣幸:被叫做从古至今最轻易的大手笔;与他对照,此外作家全都显得呆板、敦实、不懂宽容、乡下人一般直来直去。

狄德罗在《宿命论者雅克》中复制、赞赏、作弄、讽刺性地模仿了斯特恩吗?——我们不得而知,——也许这正是作者要达标的效率。正是这种疑神疑鬼使高卢鸡人相比较这部随笔很不公正,这实在是一部他们最早的大师级小说(这位大师无需在古往今来的任什么人面前感到羞愧)。高卢鸡人对幽默——尤其是对这种幽默地对待幽默的章程——正是过度认真了,是否还有必要加上一条,斯特恩是具有伟大作家里的最瞥脚的范本,根本无法变成规范,以至于狄德罗也要为他的勇猛付出代价?

137

最差劲的读者——最差劲的读者就像实施抢窃的小将:她俩拿走一些或许对她们有用的事物,把剩余的弄得一塌糊涂,还要对总体举行毁谤

138

好小说家的注明——好散文家有五个共同点:他俩宁可被人精通,而不是受人啧啧称扬;另外,他们作文不是为着这些尖刻的、过分敏锐的读者。

153

“好书需时间”——每一本好书出版之初,读起来总有些酸涩:新生事物总有弱点。倘诺作者还活着,并且还很出名,我们对她的事也拥有耳闻,那么这对书来说就特别不利:因为世人都习惯于将作者和作品混为一谈。书中的精神、美好和精髓经年历久才能展现出来,它需要敬意的抚育,这种敬意会随时日增长,而后变得陈旧,末了成为一种传统习惯。时光在地点流动,蜘蛛在地点结网,非这样不行。好的读者会让一本书变得更好,好的对手会将该书变得清楚。

167

只为自己写作——理智的大手笔只为本人的后代写作,换言之,只为自己的余生作文,以便到了当年仍可以从自己随肢体会欢乐

170

剧场里的德国人——歌德在各地点都抢先了德意志人,并且今日照例这样:他永世都不会与她们拉帮结派一个中华民族怎么配得上歌德在善的现状和善的意愿上体现出来的明察秋毫呢!正如贝多芬制作了跨越德意志联邦共和国人的音乐,叔本华创造了抢先德意志人的经济学,歌德也塑造了超越德意志人的塔索、伊菲格尼亚。追随他的是为数极少的一小批有参天修养的人,经过古典文化、生活和观光的锤炼,成功地领先了德意志联邦共和国人的天性:他协调的心愿无非也是如此。

202

玩笑——玩笑是情感的墓志铭

216

空荡荡的因由——多少极有天然的奇才,最后却一无所获,因为人性上的毛病,使她们紧缺度过漫长孕期的耐心。

228

游客及其等级——旅行者可以分为三个级次:低于的世界级是这么些在旅行中成为被看对象的人,——他们实在可以说是被别人旅行了,好像瞎了千篇一律;其次是的确自己在看世界的人第三等级的人经过看而所有经历第四阶段的人将经历融入我,并且带入今后的生活末段有那么几个人能有所一级的能力,他们经历了所见之事并把它们整个融入我,一旦回家就肯定把它们整个倒塌出来,在走路上和创作中显示出来。——所有人都在经验整个人生旅程,就像这五类游客,低于等级是彻头彻尾的消极者,最高阶段是行动者,是不遗漏任何内心经历的满面春风生活者

281

门——小孩子和男子汉一样,将兼具的经历和习得都看成是一扇扇门:但对幼儿而言,这多少个门是进口,而对男士汉而言,它们永远是过道。

337

吐弃快乐的生死存亡——我们必须制止把团结的生存建立在一个过度狭窄的私欲基础上:因为,假若您吐弃了身份、荣誉、伙伴、性欲、舒适和方法带来的喜欢,那么终有一天,我们会发现,由于这种遗弃,大家不光没能与智慧为邻,而且是离厌世不远了。

358

绝不会徒劳——在真理的主峰攀登,相对不会是纸上谈兵的:可能前几天又爬了一段,或是在积蓄力量,以便明天能爬得更高。

367

生活中尽量摆脱追随者——只有当你不再当你这一个追随者的跟随者时,你才会领会,追随者是何其微不足道。

376

链条思想家——一个勤于思考的人,每看到或听到一个新想法,就会顿时觉得这像一条链子

378

名为天才?——决定达到崇高的靶子,并且决定拿到达标崇高目的的招数。

397

国色天香灵魂的标志——漂亮的魂魄,不是充裕能飞得高高的的,而是充足没有起伏,始终处于更随心所欲、更精通的空气中和低度上的魂魄

408

走向地狱——自己也像奥德修斯同一,在炼狱里待过,而且还会常去;为了和部分遗骸谈话,我不但献上了羊肉,而且也不珍重自己的鲜血。有四对人,没有拒绝我这些献祭人:伊壁鸠鲁和蒙田,歌德和斯宾诺莎,柏拉图(Plato)和卢梭,帕斯卡和叔本华在长日子独自漫步之后,我必须要和那一个人探讨商量,即使她们互相之间交流对与错,我也乐意承受他们的对与错,并愿意倾听她们的诉说。不论自身说怎么,决定哪些,为协调和别人着想了何等:我的眼眸都紧盯在她们多少人身上,也来看他俩的眸子也紧盯在自我身上。——希望这些活着的人甘愿兼容自己,有时,他们在自我眼里就像影子,这样苍白,那样苦闷,这样不安,唉,这样贪恋生活:而这八君子在自我前面呈现如此发达,好像他们现在,也就是死后,永远不会厌倦生命。永远生气勃勃才是第一,而“永恒生命”,或者索性说生命,又何足轻重!

全局变量

Tip
避免全局变量

定义:
概念在模块级的变量.
优点:
突发性有用.
缺点:
导入时或许改动模块行为, 因为导入模块时会对模块级变量赋值.
结论:
避免使用全局变量, 用类变量来代替. 但也有一部分不一:

  1. 本子的默认选项.
  2. 模块级常量. 例如: PI = 3.14159. 常量应该全大写, 用下划线连接.
  3. 奇迹用全局变量来缓存值或者当作函数重回值很有用.
  4. 倘若需要, 全局变量应该仅在模块内部可用,
    并通过模块级的集体函数来访问.

嵌套 局部 内部类或函数

Tip
勉励接纳嵌套/本地/内部类或函数

定义:
类可以定义在艺术, 函数或者类中. 函数可以定义在模式或函数中.
封闭区间中定义的变量对嵌套函数是只读的.
优点:
允许定义仅用于有效限制的工具类和函数.
缺点:
嵌套类或局项目标实例无法体系化(pickled).
结论:
引进使用.

列表推导 List Comprehensions

Tip
可以在简单意况下使用

定义:
列表推导(list comprehensions)与生成器表明式(generator
expression)提供了一种简单高效的艺术来创造列表和迭代器, 而不必借助map(),
filter(), 或者lambda.
优点:
简简单单的列表推导可以比此外的列表成立方法尤其清晰简单.
生成器表明式能够异常急忙, 因为它们避免了创办整个列表.
缺点:
复杂的列表推导或者生成器表明式可能难以阅读.
结论:
适用于简单情状. 每个部分应该单独置于一行: 映射表明式, for语句,
过滤器表明式. 禁止多重for语句或过滤器表明式. 复杂气象下依然拔取循环.

Yes:
  result = []
  for x in range(10):
      for y in range(5):
          if x * y > 10:
              result.append((x, y))

  for x in xrange(5):
      for y in xrange(5):
          if x != y:
              for z in xrange(5):
                  if y != z:
                      yield (x, y, z)

  return ((x, complicated_transform(x))
          for x in long_generator_function(parameter)
          if x is not None)

  squares = [x * x for x in range(10)]

  eat(jelly_bean for jelly_bean in jelly_beans
      if jelly_bean.color == 'black')

No:
  result = [(x, y) for x in range(10) for y in range(5) if x * y > 10]

  return ((x, y, z)
          for x in xrange(5)
          for y in xrange(5)
          if x != y
          for z in xrange(5)
          if y != z)

默认迭代器和操作符

Tip
一旦类型襄助, 就选拔默认迭代器和操作符. 比如列表, 字典及文件等.

定义:
容器类型, 像字典和列表, 定义了默认的迭代器和涉及测试操作符(in和not in)
优点:
默认操作符和迭代器简单快速, 它们平昔发挥了操作, 没有额外的点子调用.
使用默认操作符的函数是通用的. 它可以用来扶助该操作的此外类型.
缺点:
你没法通过翻阅情势名来区别对象的门类(例如, has_key()意味着字典).
然而这也是优点.
结论:
只要类型协理, 就利用默认迭代器和操作符, 例如列表, 字典和文件.
内建项目也定义了迭代器方法. 优先考虑这多少个措施, 而不是这个再次来到列表的方法.
当然,这样遍历容器时,你将无法修改容器.

Yes:  for key in adict: ...
      if key not in adict: ...
      if obj in alist: ...
      for line in afile: ...
      for k, v in dict.iteritems(): ...

No:   for key in adict.keys(): ...
      if not adict.has_key(key): ...
      for line in afile.readlines(): ...

生成器

Tip
按需使用生成器.

定义:
所谓生成器函数, 就是每当它实施三回生成(yield)语句, 它就回去一个迭代器,
这么些迭代器生成一个值. 生成值后, 生成器函数的周转状态将被挂起,
直到下两遍生成.
优点:
简化代码, 因为每一趟调用时, 局部变量和控制流的事态都会被保存.
比起一回成立一多元值的函数, 生成器使用的内存更少.
缺点:
没有.
结论:
勉励采用. 注目的在于生成器函数的文档字符串中应用”Yields:”而不是”Returns:”.
(译者注: 参看
注释
)

Lambda函数

Tip
适用于单行函数

定义:
与话语相反, lambda在一个表明式中定义匿名函数. 常用于为 map()
filter() 之类的高阶函数定义回调函数或者操作符.
优点:
方便.
缺点:
比地点函数更难阅读和调试. 没有函数名代表堆栈跟踪更难精晓.
由于lambda函数平常只包含一个表明式, 由此其表明能力有限.
结论:
适用于单行函数. 如若代码超越60-80个字符, 最好或者定义成常规(嵌套)函数.

对此周边的操作符,例如乘法操作符,使用 operator
模块中的函数以代替lambda函数. 例如, 推荐应用 operator.mul , 而不是
lambda x, y: x * y .

原则表明式

Tip
适用于单行函数

定义:
标准表明式是对于if语句的一种更加简易的句法规则. 例如:
x = 1 if cond else 2 .
优点:
比if语句更加简明和方便.
缺点:
比if语句难于阅读. 倘使表明式很长, 难于固定条件.
结论:
适用于单行函数. 在另外意况下,推荐应用完全的if语句.

默认参数值

Tip
适用于大部分情状.

定义:
您可以在函数参数列表的尾声指定变量的值, 例如, def foo(a, b = 0): .
如若调用foo时只带一个参数, 则b被设为0. 只要带多少个参数,
则b的值等于第二个参数.
优点:
你日常会碰到一些施用大量默认值的函数,
但偶尔(相比较少见)你想要覆盖这些默认值.
默认参数值提供了一种简易的法门来完成这件事,
你不需要为这一个罕见的不同定义大量函数. 同时,
Python也不补助重载方法和函数, 默认参数是一种”仿造”重载行为的简易格局.
缺点:
默认参数只在模块加载时求值三回. 假若参数是列表或字典之类的可变类型,
这也许会导致问题. 如果函数修改了目的(例如向列表追加项),
默认值就被涂改了.
结论:
鼓励利用, 不过有如下注意事项:

并非在函数或艺术定义中动用可变对象作为默认值.

Yes: def foo(a, b=None):
         if b is None:
             b = []

No:  def foo(a, b=[]):
         ...
No:  def foo(a, b=time.time()):  # The time the module was loaded???
         ...
No:  def foo(a, b=FLAGS.my_thing):  # sys.argv has not yet been parsed...
         ...

属性 properties

Tip
做客和安装数据成员时, 你平常会动用简易, 轻量级的造访和设置函数.
提议用属性(properties)来取代它们.

定义:
一种用于包装情势调用的格局. 当运算量不大,
它是拿到和安装属性(attribute)的科班形式.
优点:
由此解除简单的属性(attribute)访问时显式的get和set方法调用, 可读性提高了.
允许懒惰的总计. 用Pythonic的主意来维护类的接口. 就性能而言,
当直接访问变量是在理的, 添加访问方法就显得琐碎而无意义.
使用性能(properties)可以绕过那一个问题.
将来也足以在不破坏接口的处境下将做客方法加上.
缺点:
特性(properties)是在get和set方法阐明后指定,
这需要使用者在接下去的代码中注意:
set和get是用于属性(properties)的(除了用 @property
装饰器创造的只读属性). 必须继续自object类.
可能隐藏比如操作符重载之类的副功用. 继承时可能会令人困惑.
结论:
你平日习惯于采用访问或设置模式来做客或安装数据, 它们简单而轻量.
可是大家提出您在新的代码中采取属性. 只读属性应该用 @property 装饰器
来创建.

如若子类没有覆盖属性, 那么属性的继续可能看起来不显著.
因而使用者必须保证走访方法直接被调用,
以保证子类中的重载方法被属性调用(使用模板方法设计格局).

Yes: import math

     class Square(object):
         """A square with two properties: a writable area and a read-only perimeter.

         To use:
         >>> sq = Square(3)
         >>> sq.area
         9
         >>> sq.perimeter
         12
         >>> sq.area = 16
         >>> sq.side
         4
         >>> sq.perimeter
         16
         """

         def __init__(self, side):
             self.side = side

         def __get_area(self):
             """Calculates the 'area' property."""
             return self.side ** 2

         def ___get_area(self):
             """Indirect accessor for 'area' property."""
             return self.__get_area()

         def __set_area(self, area):
             """Sets the 'area' property."""
             self.side = math.sqrt(area)

         def ___set_area(self, area):
             """Indirect setter for 'area' property."""
             self._SetArea(area)

         area = property(___get_area, ___set_area,
                         doc="""Gets or sets the area of the square.""")

         @property
         def perimeter(self):
             return self.side * 4

(译者注: 老实说, 我觉得这段示例代码很不合适, 有必不可少这么蛋疼吗?)

True or False的求值

Tip
尽量采用隐式false

定义:
Python在布尔上下文中会将某些值求值为false. 按简单的直觉来讲,
就是有着的”空”值都被认为是false. 由此0, None, [], {}, “”
都被认为是false.
优点:
应用Python布尔值的尺度语句更易读也更不错犯错. 大部分意况下, 也更快.
缺点:
对C/C++开发人员来说, 可能看起来有些怪.
结论:
尽可能接纳隐式的false, 例如: 使用 if foo: 而不是 if foo != []: .
可是依然有局部注意事项需要您难忘:

  1. 永久不要用==或者!=来相比较单件, 比如None. 使用is或者is not.

  2. 只顾: 当你写下 if x: 时, 你实际表示的是 if x is not None . 例如:
    当你要测试一个默认值是None的变量或参数是否被设为另外值.
    这多少个值在布尔语义下可能是false!

  3. 永久不要用==将一个布尔量与false相比. 使用 if not x: 代替.
    即便您需要区分false和None, 你应该用像 if not x and x is not None:
    这样的语句.

  4. 对此系列(字符串, 列表, 元组), 要小心空体系是false. 因而
    if not seq: 或者 if seq:if len(seq):if not len(seq):
    要更好.

  5. 处理整数时, 使用隐式false可能会得不偿失(即不小心将None当做0来拍卖).
    你能够将一个已知是整型(且不是len()的回来结果)的值与0相比较.

Yes: if not users:
         print 'no users'

     if foo == 0:
         self.handle_zero()

     if i % 10 == 0:
         self.handle_multiple_of_ten()


No:  if len(users) == 0:
         print 'no users'

     if foo is not None and not foo:
         self.handle_zero()

     if not i % 10:
         self.handle_multiple_of_ten()
  1. 专注‘0’(字符串)会被用作true.

老式的言语特征

Tip
尽可能使用字符串方法取代字符串模块. 使用函数调用语法取代apply().
使用列表推导, for循环取代filter(),map()以及reduce().

定义:
现阶段版本的Python提供了大家平时更欣赏的替代品.
结论:
我们不采用不襄助这一个特征的Python版本, 所以没理由不用新的形式.

Yes: words = foo.split(':')

     [x[1] for x in my_list if x[2] == 5]

     map(math.sqrt, data)    # Ok. No inlined lambda expression.

     fn(*args, **kwargs)

No:  words = string.split(foo, ':')

     map(lambda x: x[1], filter(lambda x: x[2] == 5, my_list))

     apply(fn, args, kwargs)

词法功用域 Lexical Scoping

Tip

推介应用

定义:
嵌套的Python函数可以引用外层函数中定义的变量, 但是无法对它们赋值.
变量绑定的剖析是行使词法效能域, 也就是依据静态的顺序文本.
对一个块中的某个名称的另外赋值都会招致Python将对该名称的万事引用当做局部变量,
甚至是赋值前的处理. 假诺赶上global注解, 该名称就会被视作全局变量.

一个使用这多少个特点的例子:

def get_adder(summand1):
    """Returns a function that adds numbers to a given number."""
    def adder(summand2):
        return summand1 + summand2

    return adder

(译者注: 这么些事例有点古怪, 你应当这么使用这么些函数:
sum = get_adder(summand1)(summand2) )
优点:
平常可以带来越来越清晰, 优雅的代码.
尤其会让有经验的Lisp和Scheme(还有Haskell, ML等)程序员感到欣慰.
缺点:
或是引致令人迷惑的bug. 例如上面这些遵照
PEP-0227
的例子:

i = 4
def foo(x):
    def bar():
        print i,
    # ...
    # A bunch of code here
    # ...
    for i in x:  # Ah, i *is* local to Foo, so this is what Bar sees
        print i,
    bar()

因此 foo([1, 2, 3]) 会打印 1 2 3 3 , 不是 1 2 3 4 .

(译者注: x是一个列表,
for循环其实是将x中的值依次赋给i.这样对i的赋值就隐式的爆发了,
整个foo函数体中的i都会被作为局部变量, 包括bar()中的那一个.
这或多或少与C++之类的静态语言依然有很大区其余.)
结论:
鼓励使用.

函数与情势装饰器

Tip
若是好处很肯定, 就明智而严格的拔取装饰器

定义:
用来函数及方法的装饰器
(也就是@标记). 最广泛的装饰器是@classmethod 和@staticmethod,
用于将常规函数转换成类方法或静态方法. 可是,
装饰器语法也允许用户自定义装饰器. 特别地, 对于某个函数 my_decorator ,
上边的两段代码是千篇一律的:

class C(object):
   @my_decorator
   def method(self):
       # method body ...
class C(object):
    def method(self):
        # method body ...
    method = my_decorator(method)

优点:
优雅的在函数上点名一些转换. 该转换可能减弱部分重新代码,
保持已有函数不变(enforce invariants), 等.
缺点:
装饰器可以在函数的参数或重回值上推行此外操作,
这说不定造成令人奇怪的隐藏行为. 而且, 装饰器在导入时执行.
从装饰器代码的挫折中平复更加不能.
结论:
只要好处很扎眼, 就明智而严苛的施用装饰器.
装饰器应该遵从和函数一样的导入和命名规则.
装饰器的python文档应该清楚的辨证该函数是一个装潢器.
请为装饰器编写单元测试.

避免装饰器自身对外场的看重性(即决不借助于文件, socket, 数据库连接等),
因为装饰器运行时这一个资源可能不可用(由 pydoc 或其他工具导入).
应该保证一个用有效参数调用的装饰器在装有境况下都是水到渠成的.

装饰器是一种相当情势的”一流代码”. 参考前面关于 Main 的话题.

线程

Tip
毫无借助内建类型的原子性.

尽管如此Python的内建档次例如字典看上去拥有原子操作,
不过在少数意况下它们如故不是原子的(即:
假诺__hash____eq__被实现为Python方法)且它们的原子性是靠不住的.
你也无法指望原子变量赋值(因为这些反过来看重字典).

先行采纳Queue模块的 Queue 数据类型作为线程间的数额通信格局. 此外,
使用threading模块及其锁原语(locking primitives).
了然条件变量的恰到好处使用办法, 这样你就足以采取 threading.Condition
来取代低级此外锁了.

威力过大的特色

Tip
制止选择那一个特点

定义:
Python是一种非凡灵活的语言, 它为您提供了广大花里胡哨的特性,
诸如元类(metaclasses), 字节码访问, 任意编译(on-the-fly compilation),
动态继承, 对象父类重定义(object reparenting), 导入黑客(import hacks),
反射, 系统内修改(modification of system internals), 等等.
优点:
无敌的言语特色, 能让你的代码更紧凑.
缺点:
选用这多少个很”酷”的表征极度诱人, 但不是相对必要.
使用奇技淫巧的代码将进一步难以阅读和调试. 先导容许还好(对原作者而言),
但当你回顾代码, 它们可能会比那一个稍长一点只是很间接的代码更加不便领会.
结论:
在你的代码中避免这么些特性.

Python风格规范

分号

Tip
不要在行尾加分号, 也不用用分号将两条命令放在同样行.

行长度

Tip
每行不超过80个字符

例外:

  1. 长的导入模块语句
  2. 诠释里的URL

决不接纳反斜杠连接行.

Python会将 圆括号,
中括号和花括号中的行隐式的连接起来

, 你可以采纳那么些特点. 虽然需要, 你可以在表达式外围扩大一对额外的圆括号.

Yes: foo_bar(self, width, height, color='black', design=None, x='foo',
             emphasis=None, highlight=0)

     if (width == 0 and height == 0 and
         color == 'red' and emphasis == 'strong'):

万一一个文本字符串在一行放不下, 能够运用圆括号来落实隐式行连接:

x = ('This will build a very long long '
     'long long long long long long string')

在诠释中,倘若必要,将长的URL放在一行上。

Yes:  # See details at
      # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html

No:  # See details at
     # http://www.example.com/us/developer/documentation/api/content/\
     # v2.0/csv_file_name_extension_full_specification.html

留意下面例子中的元素缩进; 你可以在本文的 缩进 部分找到解释.

括号

Tip
宁缺毋滥的施用括号

除非是用于落举行连接, 否则毫不在回到语句或规范语句中使用括号.
不过在元组两边使用括号是足以的.

Yes: if foo:
         bar()
     while x:
         x = bar()
     if x and y:
         bar()
     if not x:
         bar()
     return foo
     for (x, y) in dict.items(): ...

No:  if (x):
         bar()
     if not(x):
         bar()
     return (foo)

缩进

Tip
用4个空格来缩进代码

相对不用用tab, 也毫无tab和空格混用. 对于行连接的状态,
你应该如故垂直对齐换行的要素(见 行长度 部分的言传身教),
或者应用4空格的悬挂式缩进(这时第一行不应有有参数):

Yes:   # Aligned with opening delimiter
       foo = long_function_name(var_one, var_two,
                                var_three, var_four)

       # Aligned with opening delimiter in a dictionary
       foo = {
           long_dictionary_key: value1 +
                                value2,
           ...
       }

       # 4-space hanging indent; nothing on first line
       foo = long_function_name(
           var_one, var_two, var_three,
           var_four)

       # 4-space hanging indent in a dictionary
       foo = {
           long_dictionary_key:
               long_dictionary_value,
           ...
       }

No:    # Stuff on first line forbidden
      foo = long_function_name(var_one, var_two,
          var_three, var_four)

      # 2-space hanging indent forbidden
      foo = long_function_name(
        var_one, var_two, var_three,
        var_four)

      # No hanging indent in a dictionary
      foo = {
          long_dictionary_key:
              long_dictionary_value,
              ...
      }

空行

Tip
一流定义之间空两行, 方法定义之间空一行

头号定义之间空两行, 比如函数或者类定义. 方法定义,
类定义与第一个法子之间, 都应该空一行. 函数或方法中,
某些地方若是你觉得适当, 就空一行.

空格

Tip
按部就班正规的排版规范来利用标点两边的空格

括号内毫不有空格.

Yes: spam(ham[1], {eggs: 2}, [])

No:  spam( ham[ 1 ], { eggs: 2 }, [ ] )

不用在逗号, 分号, 冒号后边加空格, 但应该在它们后边加(除了在行尾).

Yes: if x == 4:
         print x, y
     x, y = y, x

No:  if x == 4 :
         print x , y
     x , y = y , x

参数列表, 索引或切片的左括号前不应加空格.

Yes: spam(1)

no: spam (1)

Yes: dict['key'] = list[index]

No:  dict ['key'] = list [index]

在二元操作符两边都增长一个空格, 比如赋值(=), 相比较(==, <, >, !=,
<>, <=, >=, in, not in, is, is not), 布尔(and, or, not).
至于算术操作符两边的空格该怎样利用, 需要您自己理想判断.
不过两侧务必要保全一致.

Yes: x == 1

No:  x<1

当’=’用于提醒关键字参数或默认参数值时, 不要在其两侧使用空格.

Yes: def complex(real, imag=0.0): return magic(r=real, i=imag)

No:  def complex(real, imag = 0.0): return magic(r = real, i = imag)

并非用空格来垂直对齐多行间的标记, 因为这会成为护卫的负担(适用于:, #,
=等):

Yes:
     foo = 1000  # comment
     long_name = 2  # comment that should not be aligned

     dictionary = {
         "foo": 1,
         "long_name": 2,
         }

No:
     foo       = 1000  # comment
     long_name = 2     # comment that should not be aligned

     dictionary = {
         "foo"      : 1,
         "long_name": 2,
         }

Python 解析器

Tip
大部分分.py文件不必以#!作为文件的开端. 遵照
PEP-394
, 程序的main文件应该以#!/usr/bin/python2或者 #!/usr/bin/python3开始.

(译者注: 在总括机科学中,
Shebang
(也号称Hashbang)是一个由井号和叹号构成的字符串行(#!),
其现出在文件文件的第一行的前六个字符. 在文书中设有Shebang的情景下,
类Unix操作系统的次序载入器会分析Shebang后的情节,
将这些情节作为解释器指令, 并调用该指令,
并将载有Shebang的文本路径作为该解释器的参数. 例如,
以指令#!/bin/sh开始的文本在进行时会实际调用/bin/sh程序.)
#!先用于支援内核找到Python解释器, 不过在导入模块时, 将会被忽略.
因而惟有被直接执行的文件中才有必不可少参预#!.

注释

Tip
担保对模块, 函数, 方法和行内注释使用正确的风格 文档字符串

Python有一种独一无二的的注释形式: 使用文档字符串. 文档字符串是包, 模块,
类或函数里的首先个语句. 那些字符串可以透过对象的doc成员被机关提取,
并且被pydoc所用. (你可以在你的模块上运行pydoc试一把, 看看它长什么样).
大家对文档字符串的老办法是接纳三重双引号”“”(
PEP-257
). 一个文档字符串应该如此协会: 首先是单排以句号,
问号或惊叹号结尾的概述(或者该文档字符串单纯只有一行). 接着是一个空行.
接着是文档字符串剩下的一对, 它应该与文档字符串的首先行的首先个引号对齐.
上面有更多文档字符串的格式化规范.
模块

每个文件应该包含一个许可样板. 遵照项目利用的特许(例如, Apache 2.0, BSD,
LGPL, GPL), 采纳合适的样板.
函数和方法

下文所指的函数,包括函数, 方法, 以及生成器.

一个函数必须要有文档字符串, 除非它满意以下规则:

  1. 表面不可见
  2. 可怜短小
  3. 简单明了

文档字符串应该包含函数做什么, 以及输入和输出的详细描述. 平日,
不应该描述”如何做”, 除非是一对犬牙交错的算法. 文档字符串应该提供充分的音信,
当旁人编写代码调用该函数时, 他不需要看一行代码,
只要看文档字符串就可以了. 对于复杂的代码,
在代码旁边加注释会比使用文档字符串更有意义.

关于函数的多少个地方应当在特定的小节中开展描述记录, 这么些地点如下文所述.
每节应该以一个标题行开首. 标题行以冒号结尾. 除标题行外,
节的其余情节应被缩进2个空格.

Args:
列出各类参数的名字, 并在名字后采纳一个冒号和一个空格,
分隔对该参数的描述.假诺描述太长超越了单行80字符,使用2或者4个空格的昂立缩进(与公事其他部分保持一致).
描述应该包括所需的档次和含义.
如若一个函数接受foo(可变长度参数列表)或者bar (任意关键字参数),
应该详细列出
foo和**bar.

Returns: (或者 Yields: 用于生成器)
叙述重返值的档次和语义. 假使函数重返None, 这一局部可以省略.

Raises:
列出与接口有关的富有非常.

def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
    """Fetches rows from a Bigtable.

    Retrieves rows pertaining to the given keys from the Table instance
    represented by big_table.  Silly things may happen if
    other_silly_variable is not None.

    Args:
        big_table: An open Bigtable Table instance.
        keys: A sequence of strings representing the key of each table row
            to fetch.
        other_silly_variable: Another optional variable, that has a much
            longer name than the other args, and which does nothing.

    Returns:
        A dict mapping keys to the corresponding table row data
        fetched. Each row is represented as a tuple of strings. For
        example:

        {'Serak': ('Rigel VII', 'Preparer'),
         'Zim': ('Irk', 'Invader'),
         'Lrrr': ('Omicron Persei 8', 'Emperor')}

        If a key from the keys argument is missing from the dictionary,
        then that row was not found in the table.

    Raises:
        IOError: An error occurred accessing the bigtable.Table object.
    """
    pass

类应该在其定义下有一个用于描述该类的文档字符串.
假如您的类有集体性质(Attributes),
那么文档中应有有一个性能(Attributes)段.
并且应该遵循和函数参数相同的格式.

class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, likes_spam=False):
        """Inits SampleClass with blah."""
        self.likes_spam = likes_spam
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""

块注释和行注释

最亟需写注释的是代码中那个技巧性的有些. 如果您在下次
代码审查
的时候必须解释一下, 那么你应当现在就给它写注释. 对于复杂的操作,
应该在其操作起来前写上多少行注释. 对于不是洞察的代码,
应在其行尾添加注释.

# We use a weighted dictionary search to find out where i is in
# the array.  We extrapolate position based on the largest num
# in the array and the array size and then do binary search to
# get the exact number.

if i & (i-1) == 0:        # true iff i is a power of 2

为了增进可读性, 注释应该至少离开代码2个空格.

另一方面, 毫无要讲述代码. 如若阅读代码的人比你更懂Python,
他只是不知晓您的代码要做什么.

# BAD COMMENT: Now go through the b array and make sure whenever i occurs
# the next element is i+1

Tip
倘使一个类不继续自此外类, 就显式的从object继承. 嵌套类也一样.

Yes: class SampleClass(object):
         pass


     class OuterClass(object):

         class InnerClass(object):
             pass


     class ChildClass(ParentClass):
         """Explicitly inherits from another class already."""

No: class SampleClass:
        pass


    class OuterClass:

        class InnerClass:
            pass

继承自 object 是为了使属性(properties)正常工作,
并且这样可以保障你的代码, 使其不受Python
3000的一个异常的秘密不兼容性影响. 这样做也定义了一些异样的方法,
那么些方法实现了对象的默认语义, 包括
__new__, __init__, __delattr__, __getattribute__, __setattr__, __hash__, __repr__, and __str__
.

字符串

Tip
即使参数都是字符串, 使用%操作符或者格式化方法格式化字符串.
不过也不可以同等对待, 你需要在+和%期间优秀判定.

Yes: x = a + b
     x = '%s, %s!' % (imperative, expletive)
     x = '{}, {}!'.format(imperative, expletive)
     x = 'name: %s; score: %d' % (name, n)
     x = 'name: {}; score: {}'.format(name, n)

No: x = '%s%s' % (a, b)  # use + in this case
    x = '{}{}'.format(a, b)  # use + in this case
    x = imperative + ', ' + expletive + '!'
    x = 'name: ' + name + '; score: ' + str(n)

避免在循环中用+和+=操作符来累加字符串. 由于字符串是不可变的,
这样做会创制不必要的暂时对象, 并且导致二次方而不是线性的运转时间.
作为代表方案, 你可以将每个子串参预列表, 然后在循环结束后用 .join
连接列表. (也可以将每个子串写入一个 cStringIO.StringIO 缓存中.)

Yes: items = ['<table>']
     for last_name, first_name in employee_list:
         items.append('<tr><td>%s, %s</td></tr>' % (last_name, first_name))
     items.append('</table>')
     employee_table = ''.join(items)

No: employee_table = '<table>'
    for last_name, first_name in employee_list:
        employee_table += '<tr><td>%s, %s</td></tr>' % (last_name, first_name)
    employee_table += '</table>'

在同一个文书中, 保持利用字符串引号的同一性.
使用单引号’或者双引号”之一用以引用字符串, 并在同等文件中沿用.
在字符串内得以运用此外一种引号, 以避免在字符串中动用.
GPyLint已经进入了这一检查.

(译者注:GPyLint疑为笔误, 应为PyLint.)

Yes:
     Python('Why are you hiding your eyes?')
     Gollum("I'm scared of lint errors.")
     Narrator('"Good!" thought a happy Python reviewer.')

No:
     Python("Why are you hiding your eyes?")
     Gollum('The lint. It burns. It burns us.')
     Gollum("Always the great lint. Watching. Watching.")

为多行字符串使用三重双引号”“”而非三重单引号’‘’.
当且仅当项目中采纳单引号’来引用字符串时,
才可能会动用三重’‘’为非文档字符串的多行字符串来标识引用.
文档字符串必须拔取三重双引号”“”. 但是要注意, 通常用隐式行连接更清楚,
因为多行字符串与程序其他部分的缩进情势不一致.

Yes:
    print ("This is much nicer.\n"
           "Do it this way.\n")

No:
      print """This is pretty ugly.
  Don't do this.
  """

文件和sockets

Tip
在文书和sockets结束时, 显式的倒闭它.

除文件外, sockets或其他类似文件的目的在没有必要的情景下打开,
会有成百上千副功用, 例如:

  1. 它们或者会损耗一定量的系统资源,如文件讲述符.即便这一个资源在利用后尚未登时归还系统,那么用于拍卖这些目的的代码会将资源消耗殆尽.
  2. 持有文件将会阻碍对于文本的别样诸如移动、删除之类的操作.
  3. 仅仅是从逻辑上关闭文件和sockets,那么它们依旧可能会被其共享的主次在无意中举行读或者写操作.唯有当它们确实被关门后,对于它们尝试举办读或者写操作将会跑出相当,并使得问题很快显现出来.

还要,幻想当文件对象析构时,文件和sockets会自行关闭,试图将文件对象的生命周期和文书的场地绑定在共同的想法,都是不现实的.
因为有如下原因:

  1. 一向不其他方法可以确保运行环境会真正的履行文书的析构.不同的Python实现采纳不同的内存管理技术,比如延时垃圾处理机制.
    延时垃圾处理机制可能会造成对象生命周期被擅自无界定的延长.
  2. 对于文本意外的引用,会造成对于文本的兼具时间超越预想(比如对于充裕的跟踪,
    包含有全局变量等).

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

with open("hello.txt") as hello_file:
    for line in hello_file:
        print line

对于不帮助采用”with”语句的近乎文件的目的,使用 contextlib.closing():

import contextlib

with contextlib.closing(urllib.urlopen("http://www.python.org/")) as front_page:
    for line in front_page:
        print line

Legacy AppEngine 中Python 2.5的代码如运用”with”语句, 需要添加
“from __future__ import with_statement”.

TODO注释

Tip
为临时代码应用TODO注释, 它是一种长期解决方案. 不算圆满, 但够好了.

TODO注释应该在所有先导处带有”TODO”字符串,
紧跟着是用括号括起来的你的名字, email地址或其余标识符.
然后是一个可选的冒号. 接着必须有一行注释, 解释要做什么样.
首要目标是为着有一个集合的TODO格式,
这样添加注释的人就足以搜寻到(并可以按需提供更多细节).
写了TODO注释并不保证写的人会亲自解决问题. 当你写了一个TODO,
请注上你的名字.

# TODO(kl@gmail.com): Use a "*" here for string repetition.
# TODO(Zeke) Change this to use relations.

倘若你的TODO是”未来做某事”的款式,
那么请保管您包含了一个点名的日子(“二〇〇九年八月缓解”)或者一个一定的事件(“等到拥有的客户都得以处理XML请求就移除那多少个代码”).

导入格式

Tip
各类导入应该占据一行

Yes: import os
     import sys

No:  import os, sys

导入总应该置身文件顶部, 位于模块注释和文档字符串之后,
模块全局变量和常量在此之前. 导入应该依据从最通用到最不通用的一一分组:

  1. 标准库导入
  2. 其三方库导入
  3. 应用程序指定导入

每种分组中, 应该依据各样模块的完整包路径按字典序排序, 忽略大小写.

import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar

语句

Tip
一般性每个语句应该占据一行

但是, 如果测试结果与测试语句在一行放得下, 你也足以将它们放在同等行.
假如是if语句, 只有在没有else时才能这么做. 特别地, 绝不要对 try/except
这样做, 因为try和except不可能放在同样行.

Yes:

  if foo: bar(foo)

No:

  if foo: bar(foo)
  else:   baz(foo)

  try:               bar(foo)
  except ValueError: baz(foo)

  try:
      bar(foo)
  except ValueError: baz(foo)

访问控制

Tip
在Python中,
对于琐碎又不太重大的走访函数,你应该一向行使国有变量来代替它们,这样可以制止额外的函数调用开销.当添加更多效益时,
你可以用属性(property)来维系语法的同等性.

(译者注: 重视封装的面向对象程序员看到这些或许会很反感,
因为她俩直白被感化: 所有成员变量都必须是个体的! 其实,
这实在是有点麻烦啊.试着去接受Pythonic哲学吧)

一面, 假如访问更扑朔迷离, 或者变量的访问开销很显然, 那么你应有使用像
get_foo()set_foo() 这样的函数调用.
假如以前的代码行为容许通过性能(property)访问 ,
那么就毫无将新的造访函数与性能绑定. 这样,
任何准备通过老方法访问变量的代码就没法运行,
使用者也就会发觉到复杂暴发了变化.

命名

Tip
module_name, package_name, ClassName, method_name,
ExceptionName,function_name, GLOBAL_VAR_NAME, instance_var_name,
function_parameter_name, local_var_name.

应该避免的名号

  1. 单字符名称, 除了计数器和迭代器.
  2. 包/模块名中的连字符(-)
  3. 双下划线开端并最后的名目(Python保留, 例如init)

命名约定

  1. 所谓”内部(Internal)”表示仅模块内可用, 或者, 在类内是维护或个人的.
  2. 用单下划线(_)开始表示模块变量或函数是protected的(使用import *
    from时不会含有).
  3. 用双下划线(__)先河的实例变量或方法表示类内私有.
  4. 将有关的类和一等函数放在同一个模块里. 不像Java,
    没必要限制一个类一个模块.
  5. 对类名使用大写字母伊始的单词(如CapWords,即Pascal风格),可是模块名应当用小写加下划线的艺术(如lower_with_under.py).
    固然已经有过多现存的模块使用类似于CapWords.py这样的命名,但前些天早已不鼓励这样做,因为只要模块名正要和类一致,
    这会令人烦扰.
Type Public Internal
Modules lower_with_under _lower_with_under
Packages lower_with_under
Classes CapWords _CapWords
Exceptions CapWords
Functions lower_with_under() lower_with_under()
Global/Class Constants CAPS_WITH_UNDER CAPS_WITH_UNDER
Global/Class Variables lower_with_under lower_with_under
Instance Variables lower_with_under _lower_with_under (protected) or __lower_with_under (private)
Method Names lower_with_under() _lower_with_under() (protected) or __lower_with_under() (private)
Function/Method Parameters lower_with_under
Local Variables lower_with_under

Python之父Guido推荐的专业

Type Public Internal
Modules lower_with_under _lower_with_under
Packages lower_with_under
Classes CapWords _CapWords
Exceptions CapWords
Functions lower_with_under() lower_with_under()
Global/Class Constants CAPS_WITH_UNDER CAPS_WITH_UNDER
Global/Class Variables lower_with_under lower_with_under
Instance Variables lower_with_under _lower_with_under (protected) or __lower_with_under (private)
Method Names lower_with_under() _lower_with_under() (protected) or __lower_with_under() (private)
Function/Method Parameters lower_with_under
Local Variables lower_with_under

Main

Tip
不畏是一个打算被当作脚本的文书,也应该是可导入的.并且简单的导入不应该导致那些本子的主功用(mainfunctionality)被实施,
这是一种副效能. 主效率应该放在一个main()函数中.

在Python中, pydoc以及单元测试要求模块必须是可导入的.
你的代码应该在执行主程序前总是检查 if __name__ == '__main__' ,
这样当模块被导入时主程序就不会被执行.

def main():
      ...

if __name__ == '__main__':
    main()

富有的世界级代码在模块导入时都会被执行. 要小心不要去调用函数,
创制对象或者执行这一个不应当在应用pydoc时实施的操作.

临别赠言

请务必保持代码的一致性

要是你正在编纂代码,
花几分钟看一下普遍代码,然后决定风格.即使它们在有着的算术操作符两边都采纳空格,那么你也应当这么做.
如若它们的诠释都用标记包围起来, 那么你的注明也要那样.

创设风格指南的目的在于让代码有规可循,这样人们就足以小心于”你在说哪些”,而不是”你在怎么说”.我们在此地给出的是全局的规范,
然则地面的标准同样紧要.借使您加到一个文件里的代码和原来代码暗淡无光,它会让读者无所适从.制止这种处境.

参考: