{"id":22407643,"url":"https://github.com/xavierjiezou/python-style-guide","last_synced_at":"2025-08-21T15:16:59.739Z","repository":{"id":108193423,"uuid":"491014638","full_name":"XavierJiezou/Python-Style-Guide","owner":"XavierJiezou","description":"Style Guide for Python.","archived":false,"fork":false,"pushed_at":"2022-05-12T12:01:45.000Z","size":25,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-25T11:01:59.581Z","etag":null,"topics":["google","guide","python","style"],"latest_commit_sha":null,"homepage":"https://XavierJiezou.github.io/Python-Style-Guide/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/XavierJiezou.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-11T08:06:27.000Z","updated_at":"2022-05-12T10:00:01.000Z","dependencies_parsed_at":"2023-03-31T11:20:18.686Z","dependency_job_id":null,"html_url":"https://github.com/XavierJiezou/Python-Style-Guide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/XavierJiezou/Python-Style-Guide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XavierJiezou%2FPython-Style-Guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XavierJiezou%2FPython-Style-Guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XavierJiezou%2FPython-Style-Guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XavierJiezou%2FPython-Style-Guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/XavierJiezou","download_url":"https://codeload.github.com/XavierJiezou/Python-Style-Guide/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XavierJiezou%2FPython-Style-Guide/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261304207,"owners_count":23138294,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google","guide","python","style"],"created_at":"2024-12-05T11:14:57.934Z","updated_at":"2025-06-22T14:02:53.640Z","avatar_url":"https://github.com/XavierJiezou.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Python-Style-Guide\n\n在谷歌提出的 Python 编程规范上进行了简化 😊，让你快速养成良好的编程习惯 ✍，开发高质量代码 🚀。\n\n- [Python-Style-Guide](#python-style-guide)\n  - [1. 背景知识](#1-背景知识)\n  - [2. 语言规范](#2-语言规范)\n    - [2.1. Lint](#21-lint)\n    - [2.2. 导入](#22-导入)\n    - [2.3. 包](#23-包)\n    - [2.4. 异常](#24-异常)\n    - [2.5. 全局变量](#25-全局变量)\n    - [2.6. 嵌套/局部/内部 类或函数](#26-嵌套局部内部-类或函数)\n    - [2.7. 推导式和生成式](#27-推导式和生成式)\n    - [2.8. 默认迭代器和操作符](#28-默认迭代器和操作符)\n    - [2.9. 生成器](#29-生成器)\n    - [2.10. Lambda 函数](#210-lambda-函数)\n    - [2.11. 条件表达式](#211-条件表达式)\n    - [2.12. 默认参数值](#212-默认参数值)\n    - [2.13. Properties](#213-properties)\n    - [2.14. True/False 的取值](#214-truefalse-的取值)\n    - [2.15. Lexical Scoping](#215-lexical-scoping)\n    - [2.16. 函数与方法装饰器](#216-函数与方法装饰器)\n    - [2.17. 线程](#217-线程)\n    - [2.18. 花哨的功能](#218-花哨的功能)\n    - [2.19. 现代化的 Python](#219-现代化的-python)\n    - [2.20. 代码类型注释](#220-代码类型注释)\n  - [3. 风格规范](#3-风格规范)\n    - [3.1. 分号](#31-分号)\n    - [3.2. 行长度](#32-行长度)\n    - [3.3. 圆括号](#33-圆括号)\n    - [3.4. 缩进](#34-缩进)\n    - [3.5. 序列元素尾部的逗号如何处理？](#35-序列元素尾部的逗号如何处理)\n    - [3.6. 空行](#36-空行)\n    - [3.7. 空格](#37-空格)\n    - [3.8. Shebang Line](#38-shebang-line)\n    - [3.9. 注释和文档字符串](#39-注释和文档字符串)\n    - [3.10. 类](#310-类)\n    - [3.11. 字符串](#311-字符串)\n    - [3.12. 文件，Sockets，以及类似的有状态的资源](#312-文件sockets以及类似的有状态的资源)\n    - [3.13. TODO 注释](#313-todo-注释)\n    - [3.14. 导入格式](#314-导入格式)\n    - [3.15. 语句](#315-语句)\n    - [3.16. Getters 与 Setters](#316-getters-与-setters)\n    - [3.17. 命名](#317-命名)\n    - [3.18. Main](#318-main)\n    - [3.19. 函数长度](#319-函数长度)\n    - [3.20. 类型注释](#320-类型注释)\n  - [4. 辅助工具](#4-辅助工具)\n    - [4.1. Python](#41-python)\n      - [4.1.1. 使用截图](#411-使用截图)\n    - [4.2. autoDocstring](#42-autodocstring)\n      - [4.2.1. 使用截图](#421-使用截图)\n    - [4.3. Python Type Hint](#43-python-type-hint)\n      - [4.3.1. 使用截图](#431-使用截图)\n  - [5. 引用参考](#5-引用参考)\n\n## 1. 背景知识\n\n不只是 Python 语言，一个比较系统的编程规范对于任何语言来说都是必须的，特别是在团队开发和协同开发中。此外，对于个人开发者，也应该花费一些时间来了解编程规范，这有助于你开发高质量代码，提高代码可读性，方便版本迭代和他人阅读。\n\n## 2. 语言规范\n\n### 2.1. Lint\n\n\u003e 使用 [pylint](https://github.com/PyCQA/pylint) 检查代码中存在的 bug。\n\n同时，谷歌也给出了推荐的 pylint 配置文件：[点击下载](https://google.github.io/styleguide/pylintrc)。\n\n具体使用方式请参考 pylint [官方文档](https://pylint.pycqa.org/en/latest/)。\n\n### 2.2. 导入\n\n\u003e 使用 import 语句导入包和模块，而不单独导入函数或类。\n\n### 2.3. 包\n\n\u003e 应该根据包的完整路径来导入模块。\n\n✅\n\n```python\nfrom doctor.who import jodie\n```\n\n⛔\n\n```python\nimport jodie\n```\n\n### 2.4. 异常\n\n\u003e 非必要不使用 try/except；遇到异常时，应该抛出有助于调试的信息。\n\n✅\n\n```python\nif minimum \u003c 1024:\n    raise ValueError(f'Min. port must be at least 1024, not {minimum}.')\nport = self._find_next_open_port(minimum)\nif port is None:\n    raise ConnectionError(f'Could not connect to service on port {minimum} or higher.')\nassert port \u003e= minimum, (f'Unexpected port {port} when minimum was {minimum}.')\n```\n\n🚨\n\n```python\nassert minimum \u003e= 1024, 'Minimum port must be at least 1024.'\nport = self._find_next_open_port(minimum)\nassert port is not None\n```\n\n### 2.5. 全局变量\n\n\u003e 避免使用全局变量，推荐使用模块级别的常量。如：`MAX_HOLY_HANDGRENADE_COUNT = 3`，常量名称全部大写，使用 `_` 分隔。\n\n### 2.6. 嵌套/局部/内部 类或函数\n\n\u003e 尽量避免使用嵌套类或函数。\n\n### 2.7. 推导式和生成式\n\n\u003e 可以在简单情况下使用推导式和生产时，但不要在复杂情况下使用，不然会导致代码可读性不好。\n\n✅\n\n```python\n[i for i in range(3)]\n```\n\n🚨\n\n```python\nreturn ((x, y, z)\n        for x in range(5)\n        for y in range(5)\n        if x != y\n        for z in range(5)\n        if y != z)\n```\n\n### 2.8. 默认迭代器和操作符\n\n\u003e 如果类型支持，就使用默认的迭代器和操作符\n\n✅\n\n```python\nfor key in adict: ...\nif key not in adict: ...\nif obj in alist: ...\nfor line in afile: ...\nfor k, v in adict.items(): ...\nfor k, v in six.iteritems(adict): ...\n```\n\n🚨\n\n```python\nfor key in adict.keys(): ...\nif not adict.has_key(key): ...\nfor line in afile.readlines(): ...\nfor k, v in dict.iteritems(): ...\n```\n\n### 2.9. 生成器\n\n\u003e 按需使用生成器。\n\n### 2.10. Lambda 函数\n\n\u003e 适用于单行函数。\n\n### 2.11. 条件表达式\n\n\u003e 仅在简单的情况下使用。\n\n✅\n\n```python\none_line = 'yes' if predicate(value) else 'no'\n```\n\n🚨\n\n```python\nbad_line_breaking = ('yes' if predicate(value) else\n                     'no')\n```\n\n### 2.12. 默认参数值\n\n\u003e 可以使用，但不要在函数或方法中定义可变对象作为默认值。\n\n✅\n\n```python\ndef foo(a, b=None):\n    if b is None:\n        b = []\ndef foo(a, b: Optional[Sequence] = None):\n    if b is None:\n        b = []\ndef foo(a, b: Sequence = ()):  # Empty tuple OK since tuples are immutable\n         ...\n```\n\n🚨\n\n```python\ndef foo(a, b=[]):\n    ...\ndef foo(a, b=time.time()):  # The time the module was loaded???\n         ...\ndef foo(a, b: Mapping = {}):  # Could still get passed to unchecked code\n         ...\n```\n\n### 2.13. Properties\n\n\u003e 推荐使用装饰器 @property 来创建拥有简单计算逻辑的属性。\n\n### 2.14. True/False 的取值\n\n\u003e 尽可能隐式的使用 False。（增加可读性）\n\nPython 会将下列这些值认定为 False：\n\n- None（空值）\n- 0（int 类型的零）\n- []（空列表）\n- {}（空字典）\n- ''（空字符串）\n\n✅\n\n```python\nif not users:\n         print('no users')\n\nif i % 10 == 0:\n    self.handle_multiple_of_ten()\n\ndef f(x=None):\n    if x is None:\n        x = []\n```\n\n🚨\n\n```python\nif len(users) == 0:\n         print('no users')\n\nif not i % 10:\n    self.handle_multiple_of_ten()\n\ndef f(x=None):\n    x = x or []\n```\n\n### 2.15. Lexical Scoping\n\n\u003e 推荐使用语法作用域。\n\nPython 是 Lexical Scoping，而并非 Dynamic Scoping。（点击[这里](https://zhuanlan.zhihu.com/p/67965089)了解更多关于 Python 作用域的知识）\n\n### 2.16. 函数与方法装饰器\n\n\u003e 避免使用 `@staticmethod`，限制 `@classmethod`。\n\n`@staticmethod` 和 `@classmethod` 是最常见的装饰器。\n\n- `@staticmethod`：将普通函数转换成类的静态方法。\n- `@classmethod`：将普通函数转换成类方法。\n\n使用装饰器使代码变得优雅，但如果报错将很难捕捉和处理，因此要谨慎选择。\n\n### 2.17. 线程\n\n\u003e 推荐使用 Quenu 模块里面的 Quenu 数据类型作为线程间的数据通信方式。不建议使用 Python 内建数据类型，例如字典。\n\n### 2.18. 花哨的功能\n\n\u003e 避免使用 Python 中花哨的功能，例如自定义元类，字节码访问等。\n\n### 2.19. 现代化的 Python\n\n\u003e Python 目前已经全面进入 3 时代了，对于需要继续支持 2.7 的历史遗留代码，请导入：\n\n```python\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n```\n\n### 2.20. 代码类型注释\n\n\u003e 建议根据 [PEP-484](https://www.python.org/dev/peps/pep-0484/) 对代码进行注释。\n\n✅\n\n```python\ndef func(a: int) -\u003e List[int]:\n    \"\"\"_summary_\n\n    Args:\n        a (int): _description_\n\n    Returns:\n        List[int]: _description_\n    \"\"\"\n  return [a]\n```\n\n🚨\n\n```python\ndef func(a):\n  return [a]\n```\n\n## 3. 风格规范\n\n### 3.1. 分号\n\n\u003e 不要在行尾加入分号，也不要用分号将两条语句放在同一行。\n\n毕竟 Python 不是 C/C++。\n\n### 3.2. 行长度\n\n\u003e 每行不要超过 80 个字符。\n\n但也有一些例外情况，如下：\n\n- 模块导入语句\n- URL，路径等标记\n- 一些不便于换行的的语句\n\n✅\n\n```python\nSee details at\n# http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html\n```\n\n🚨\n\n```python\n# See details at\n# http://www.example.com/us/developer/documentationapi/content/\\\n# v2.0/csv_file_name_extension_full_specification.html\n```\n\n### 3.3. 圆括号\n\n\u003e 尽量避免在返回语句和条件语句中使用圆括号。元组，行连接除外。\n\n✅\n\n```python\nif foo:\n    bar()\nwhile x:\n    x = bar()\nif x and y:\n    bar()\nif not x:\n    bar()\n# For a 1 item tuple the ()s are more visuallyobvious than the comma.\nonesie = (foo,)\nreturn foo\nreturn spam, beans\nreturn (spam, beans)\nfor (x, y) in dict.items(): ...\n```\n\n🚨\n\n```python\nif (x):\n    bar()\nif not(x):\n    bar()\nreturn (foo)\n```\n\n### 3.4. 缩进\n\n\u003e 使用 4 个空格来缩进代码。\n\n✅\n\n```python\n# Aligned with opening delimiter\nfoo = long_function_name(var_one, var_two,\n                         var_three, var_four)\nmeal = (spam,\n        beans)\n# Aligned with opening delimiter in a dictionary\nfoo = {\n    'long_dictionary_key': value1 +\n                           value2,\n    ...\n}\n# 4-space hanging indent; nothing on first line\nfoo = long_function_name(\n    var_one, var_two, var_three,\n    var_four)\nmeal = (\n    spam,\n    beans)\n# 4-space hanging indent in a dictionary\nfoo = {\n    'long_dictionary_key':\n        long_dictionary_value,\n    ...\n}\n```\n\n🚨\n\n```python\n# Stuff on first line forbidden\nfoo = long_function_name(var_one, var_two,\n    var_three, var_four)\nmeal = (spam,\n    beans)\n# 2-space hanging indent forbidden\nfoo = long_function_name(\n  var_one, var_two, var_three,\n  var_four)\n# No hanging indent in a dictionary\nfoo = {\n    'long_dictionary_key':\n    long_dictionary_value,\n    ...\n}\n```\n\n### 3.5. 序列元素尾部的逗号如何处理？\n\n\u003e 当 `]`，`)`，`}` 和序列最后一个元素不在同一行时，推荐在最后一个元素后面加上逗号，否则不加。\n\n✅\n\n```python\ngolomb3 = [0, 1, 3]\ngolomb4 = [\n    0,\n    1,\n    4,\n    6,\n]\n```\n\n🚨\n\n```python\ngolomb4 = [\n    0,\n    1,\n    4,\n    6\n]\n```\n\n### 3.6. 空行\n\n\u003e 顶级定义如函数或类空 2 行；方法定义及 `class` 所在的行和第一个方法间空 1 行。`def` 行之后也不要添加空行。\n\n### 3.7. 空格\n\n\u003e 逗号之前不要空格，逗号之后加一个空格，括号内不要有多余空格。\n\n✅\n\n```python\n# Case 1\nspam(ham[1], {'eggs': 2}, [])\n\n# Case 2\nif x == 4:\n    print(x, y)\nx, y = y, x\n\n# Case 3\nspam(1)\n\n# Case 4\ndict['key'] = list[index]\n\n# Case 5\nx == 1\n\n# Case 6\ndef complex(real, imag=0.0): return Magic(r=real, i=imag)\ndef complex(real, imag: float = 0.0): return Magic(r=real, i=imag)\n```\n\n🚨\n\n```python\n# Case 1\nspam( ham[ 1 ], { 'eggs': 2 }, [ ] )\n\n# Case 2\nif x == 4 :\n    print(x , y)\nx , y = y , x\n\n# Case 3\nspam (1)\n\n# Case 4\ndict ['key'] = list [index]\n\n# Case 5\nx==1\n\n# Case 6\ndef complex(real, imag = 0.0): return Magic(r = real, i = imag)\ndef complex(real, imag: float=0.0): return Magic(r = real, i = imag)\n```\n\n### 3.8. Shebang Line\n\n\u003e 大多数 `.py` 文件不必以 `#!` 作为文件的开始，程序的启动主文件最好以 `#!/usr/bin/python3` 打头。（方便内核查找 Python 解释器）\n\n### 3.9. 注释和文档字符串\n\n\u003e 确保对模块、函数、方法、行内注释使用正确的风格。\n\n**模块**的开头应该是对其内容和用法的描述：\n\n```python\n\"\"\"A one line summary of the module or program, terminated by a period.\n\nLeave one blank line.  The rest of this docstring should contain an\noverall description of the module or program.  Optionally, it may also\ncontain a brief description of exported classes and functions and/or usage\nexamples.\n\n  Typical usage example:\n\n  foo = ClassFoo()\n  bar = foo.FunctionBar()\n\"\"\"\n```\n\n**函数**和**方法**应该使用类似如下的注释：\n\n```python\ndef fetch_smalltable_rows(table_handle: smalltable.Table,\n                          keys: Sequence[Union[bytes, str]],\n                          require_all_keys: bool = False,\n) -\u003e Mapping[bytes, tuple[str, ...]]:\n    \"\"\"Fetches rows from a Smalltable.\n\n    Retrieves rows pertaining to the given keys from the Table instance\n    represented by table_handle.  String keys will be UTF-8 encoded.\n\n    Args:\n        table_handle: An open smalltable.Table instance.\n        keys: A sequence of strings representing the key of each table\n          row to fetch.  String keys will be UTF-8 encoded.\n        require_all_keys: If True only rows with values set for all keys will be\n          returned.\n\n    Returns:\n        A dict mapping keys to the corresponding table row data\n        fetched. Each row is represented as a tuple of strings. For\n        example:\n\n        {b'Serak': ('Rigel VII', 'Preparer'),\n         b'Zim': ('Irk', 'Invader'),\n         b'Lrrr': ('Omicron Persei 8', 'Emperor')}\n\n        Returned keys are always bytes.  If a key from the keys argument is\n        missing from the dictionary, then that row was not found in the\n        table (and require_all_keys must have been False).\n\n    Raises:\n        IOError: An error occurred accessing the smalltable.\n    \"\"\"\n```\n\n**类**：\n\n```python\nclass SampleClass:\n    \"\"\"Summary of class here.\n\n    Longer class information....\n    Longer class information....\n\n    Attributes:\n        likes_spam: A boolean indicating if we like SPAM or not.\n        eggs: An integer count of the eggs we have laid.\n    \"\"\"\n\n    def __init__(self, likes_spam: bool = False):\n        \"\"\"Inits SampleClass with blah.\"\"\"\n        self.likes_spam = likes_spam\n        self.eggs = 0\n\n    def public_method(self):\n        \"\"\"Performs operation blah.\"\"\"\n```\n\n**块注释**和**行注释**：\n\n```python\n# We use a weighted dictionary search to find out where i is in\n# the array.  We extrapolate position based on the largest num\n# in the array and the array size and then do binary search to\n# get the exact number.\n\nif i \u0026 (i-1) == 0:  # True if i is 0 or a power of 2.\n```\n\n### 3.10. 类\n\n\u003e 如果一个类不需要继承其它类，就显式地从 `object` 继承。\n\n✅\n\n```python\nclass SampleClass(object):\n  pass\n```\n\n🚨\n\n```python\nclass SampleClass:\n  pass\n```\n\n继承 `object` 是为了使 `properties` 正常工作，并且也继承了对象的一些方法，包括：\n\n- `__new__`\n- `__init__`\n- `__delattr__`\n- `__getattribute__`\n- `__setattr__`\n- `__hash__`\n- `__repr__`\n- `__str__`\n\n### 3.11. 字符串\n\n\u003e 使用 `f-string`，`%`，或者 `format` 方法来格式化字符串。\n\n✅\n\n```python\nn = 'John'\ns = f'name: {n}'\n```\n\n🚨\n\n```python\nn = 'John'\ns = 'name:' + n\n```\n\n避免在循环中使用 `+` 或 `+=` 来累加字符串。替代的是，使用 `''.join()`，因为该方法实现复杂度更低。\n\n✅\n\n```python\nx = ['a', 'b', 'c']\ns = ''\nfor i in x:\n    s += i\n```\n\n🚨\n\n```python\nx = ['a', 'b', 'c']\ns = ''.join(x)\n```\n\n在同一个文件中，应该使用一致的字符串引号，要使用单引号就都使用单引号，要使用双引号就都使用双引号，非必要情况不要滥用。\n\n如果一个字符串太长需要占多行，推荐使用三层双引号，而非三层单引号，并且多行字符串的位置不应该随着代码的缩进调整而改变。\n\n✅\n\n```python\nlong_string = \"\"\"This is fine if your use case can accept\n    extraneous leading spaces.\"\"\"\n```\n\n🚨\n\n```python\nlong_string = \"\"\"This is pretty ugly.\nDon't do this.\n\"\"\"\n```\n\n日志记录中字符串的使用有些特殊。推荐使用 `%` 加占位符这种方式，而不是 `f-string`。\n\n✅\n\n```python\nimport tensorflow as tf\nlogger = tf.get_logger()\nlogger.info('TensorFlow Version is: %s', tf.__version__)\n```\n\n🚨\n\n```python\nimport tensorflow as tf\nlogger = tf.get_logger()\nlogger.info(f'TensorFlow Version is: {tf.__version__}')\n```\n\n### 3.12. 文件，Sockets，以及类似的有状态的资源\n\n\u003e 文件和 Sockets 使用结束后，显式地关闭它们。推荐使用 with 语句来管理文件。\n\n### 3.13. TODO 注释\n\n\u003e 可以使用 `TODO` 为临时代码，短期或不够完美的解决方案添加注释。\n\n推荐的 TODO 格式如下：\n\n```python\n# TODO(kl@gmail.com): Use a \"*\" here for string repetition.\n# TODO(Zeke) Change this to use relations.\n```\n\n笔者自己经常使用的样式：\n\n```python\n# TODO (name, email): Description.\n```\n\n### 3.14. 导入格式\n\n\u003e 每个导入都应该是单独的一行，当然也有例如，比如 `typing`。\n\n✅\n\n```python\nimport os\nimport sys\n```\n\n🚨\n\n```python\nimport os, sys\n```\n\n此外，如果你需要导入很多库，那么应该按照先标准库，后第三方库，最后是自定义库的顺序分组导入。不同组之间空一行，同组库应该按照其首字母的 Unicode 编码排序。示例如下：\n\n```python\nimport collections\nimport queue\nimport sys\n\nfrom absl import app\nfrom absl import flags\nimport bs4\nimport cryptography\nimport tensorflow as tf\n\nfrom myproject.backend import huxley\nfrom myproject.backend.hgwells import time_machine\nfrom myproject.backend.state_machine import main_loop\nfrom otherproject.ai import body\nfrom otherproject.ai import mind\n```\n\n### 3.15. 语句\n\n\u003e 通常来说，每个语句应该占单独的一行。\n\n如果只有简单的 if 而不需要 else，你也可以将它们放一行：\n\n✅\n\n```python\nif foo: bar(foo)\n```\n\n🚨\n\n```python\nif foo: bar(foo)\nelse:   baz(foo)\n```\n\n`try/except` 语句绝对不能放同一行：\n\n✅\n\n```python\ntry:\n    bar(foo)\nexcept ValueError:\n    baz(foo)\n```\n\n⛔\n\n```python\ntry: bar(foo)\nexcept ValueError: baz(foo)\n```\n\n### 3.16. Getters 与 Setters\n\n\u003e 当获取和设置变量很复杂或成本很高时，可以使用 getters 和 setters。\n\n### 3.17. 命名\n\n\u003e 模块、包、类以及函数等推荐按照如下方式运行。\n\n- 模块名：module_name\n- 包名：package_name\n- 类名：ClassName\n- 方法名：method_name\n- 异常名：ExceptionName\n- 函数名：function_name\n- 全局常量名：GLOBAL_CONSTANT_NAME\n- 全局变量名：global_var_name\n- 实例变量名：instance_var_name\n- 函数参数名：function_parameter_name\n- 局部变量名：local_var_name\n- query_proper_noun_for_thing\n- send_acronym_via_https\n\n命名时应尽量避免使用单个字符名称，但以下情况除外：\n\n- `i`，`j`，`k`，`v` 在计数器或迭代器中的应用\n- `e` 表示 `try/except` 中的异常\n- `f` 表示 `with` 语句中的文件句柄\n\n包名和模块名避免使用连字符 `-` 连接，替换方案是下划线 `_`。\n\n不要使用双下划线打头单下划线结尾或单下划线打头双下划线结尾结尾的命名，因为这是 Python 保留的。\n\n变量命名不要带有变量的类型。比如，你想定义一个变量，并且你需要将其赋值为字典类型，你可能会将其命名为 `foo_dict`，但这是不推荐的，仅仅命名为 `foo` 即可。\n\n单下划线开头表示的模块变量或函数是受保护的。也就是说，当你使用 `from module_name import *` 时不会包含。\n\n双下划线开头的实例变量或方法表示类内私有。但是不推荐使用，因为影响可读性，并且也不是真正意义上的私有。\n\nPython 之父 Guido 推荐的命名方式如下：\n\n| Type                       | Public             | Internal                         |\n| -------------------------- | ------------------ | -------------------------------- |\n| Packages                   | lower_with_under   |                                  |\n| Modules                    | lower_with_under   | \\_lower_with_under               |\n| Classes                    | CapWords           | \\_CapWords                       |\n| Exceptions                 | CapWords           |                                  |\n| Functions                  | lower_with_under() | \\_lower_with_under()             |\n| Global/Class Constants     | CAPS_WITH_UNDER    | \\_CAPS_WITH_UNDER                |\n| Global/Class Variables     | lower_with_under   | \\_lower_with_under               |\n| Instance Variables         | lower_with_under   | \\_lower_with_under (protected)   |\n| Method Names               | lower_with_under() | \\_lower_with_under() (protected) |\n| Function/Method Parameters | lower_with_under   |                                  |\n| Local Variables            | lower_with_under   |                                  |\n\n### 3.18. Main\n\n\u003e 将真正执行的语句放在 `if __name__ == '__main__'` 入口下。\n\n示例如下：\n\n```python\ndef main():\n    ...\n\nif __name__ == '__main__':\n    main()\n```\n\n如果是使用 `absl`，使用 `app.run`：\n\n```python\nfrom absl import app\n...\n\ndef main(argv: Sequence[str]):\n    # process non-flag arguments\n    ...\n\nif __name__ == '__main__':\n    app.run(main)\n```\n\n### 3.19. 函数长度\n\n\u003e 函数块不要太长，保证短小精悍。\n\n太长的函数不便于阅读，尽量不要超过 40 行。\n\n### 3.20. 类型注释\n\n\u003e 请参考 [PEP-484](https://peps.python.org/pep-0484/) 进行类型注释。对于容易出现类型错误的代码进行注释。在代码的安全性、清晰性和灵活性上进行权衡是否注释。\n\n增加类型注释后，函数声明会变长，可以在多行显示，但要保证同一个变量和其对应的类型注释在同一行：\n\n```python\ndef my_method(self,\n              first_var: int,\n              second_var: Foo,\n              third_var: Optional[Bar]) -\u003e int:\n  ...\n```\n\n当然，下面这样也是可以的：\n\n```python\ndef my_method(\n    self, other_arg: Optional[MyLongType]\n) -\u003e dict[OtherLongType, MyLongType]:\n  ...\n```\n\n对于泛型类型类型，比如列表，最好也指定列表内元素的类型：\n\n```python\ndef get_names(employee_ids: list[int]) -\u003e dict[int, Any]:\n  ...\n```\n\n如果不指定列表元素的类型，则默认是 `Any`，就是接受所有类型的输入。\n\n## 4. 辅助工具\n\n推荐使用 VSCode 开发，因为 VSCode 提供了非常多的 Python 开发辅助插件，能极大地提高开发效率。下面是笔者自用的几款插件，在此推荐一波。\n\n### 4.1. [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)\n\n微软官方提供的 Python 开发插件，支持的功能如下：\n\n- 智能提示\n- 语法审查\n- 代码导航\n- 格式化代码\n- 调测与测试\n- ...\n\n该插件集成了 Jupyter 支持，可轻松创建、编辑或预览 `.ipynb` 文件。此外，还继承了 TensorBoard，可轻松创建一个 TensorBoard 服务，并在 VSCode 窗口内预览深度模型的训练过程。\n\n#### 4.1.1. 使用截图\n\n- 选择 Python 解释器\n\n![interpreter](https://raw.githubusercontent.com/microsoft/vscode-python/main/images/InterpreterSelectionZoom.gif)\n\n- 运行和调试代码\n\n![debug](https://raw.githubusercontent.com/microsoft/vscode-python/main/images/ConfigureDebugger.gif)\n\n- 单元测试\n\n![test](https://raw.githubusercontent.com/microsoft/vscode-python/main/images/ConfigureTests.gif)\n\n- Jupyter\n\n![jupyter](https://raw.githubusercontent.com/microsoft/vscode-python/main/images/OpenOrCreateNotebook.gif)\n\n### 4.2. [autoDocstring](https://marketplace.visualstudio.com/items?itemName=njpwerner.autodocstring)\n\nautoDocstring 用于快速生成函数的文档字符串注释，支持的功能如下：\n\n- 快速生成可以通过标签浏览的文档字符串片段；\n- 在几种不同类型的文档字符串格式之间进行选择；（比如本文提到的谷歌规范）\n- 通过 pep484 类型提示、默认值和变量名称推断参数类型；\n- 支持 args、kwargs、装饰器、错误和参数类型。\n\n#### 4.2.1. 使用截图\n\n![demo](https://github.com/NilsJPWerner/autoDocstring/raw/HEAD/images/demo.gif)\n\n### 4.3. [Python Type Hint](https://marketplace.visualstudio.com/items?itemName=njqdev.vscode-python-typehint)\n\n为 Python 提示类型提示并自动补全，支持的功能如下：\n\n- 为内置类型、估计类型和类型模块提供类型提示完成项。\n- 估计作为完成项提供的正确类型。\n- 可以在工作区中搜索 Python 文件以进行类型估计。\n\n使用该插件搭配 autoDocstring 和 Python 内置库 [typing](https://docs.python.org/3/library/typing.html) 实现完美的 Python 注释编写。\n\n#### 4.3.1. 使用截图\n\n![demo](https://github.com/njqdev/vscode-python-typehint/raw/master/images/demo.gif)\n\n---\n\n当然，如果你没有注释的需求，不需要安装 autoDocstring 和 Python Type Hint，仅仅安装微软官方提供的 Python 插件就够了，它几乎集成了开发中要用到的所有功能。虽然还有很多好用的插件，像 Python Preview 和 python snippets，但其实也没必要安装。插件不是越多越好，多了之后会造成 VSCode 卡顿，影响开发体验，多个具有相同功能的插件之间也会导致冲突。\n\n## 5. 引用参考\n\n\u003e - [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html) \n\u003e - [Python 风格指南（中文版）](https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxavierjiezou%2Fpython-style-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxavierjiezou%2Fpython-style-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxavierjiezou%2Fpython-style-guide/lists"}