python-style-guide
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePython Style Guide
Python 风格指南
Comprehensive guidelines for writing clean, maintainable Python code based on Google's Python Style Guide.
本指南基于Google Python Style Guide编写,为编写清晰、可维护的Python代码提供全面规范。
Core Philosophy
核心理念
BE CONSISTENT. Match the style of the code around you. Use these guidelines as defaults, but always prioritize consistency with existing code.
保持一致性。优先适配周边已有代码的风格,本指南作为默认规范使用,但现有代码的一致性优先级更高。
Language Rules
语言规则
Imports
导入(Imports)
Use statements for packages and modules in application code to avoid circular dependencies. For standard library and third-party packages, importing classes is acceptable.
importYes:
python
from pydantic import BaseModel # Third-party: Class import OK
from pathlib import Path # Stdlib: Class import OK
import sound_effects.utils # App: Module import
from myproject import config # App: Module importNo:
python
from myproject.utils import heavy_function # App: Avoid direct function import if circular dep risk应用代码中使用语句导入包和模块,避免循环依赖。标准库和第三方包允许直接导入类。
import✅ 正确示例:
python
from pydantic import BaseModel # 第三方库:允许导入类
from pathlib import Path # 标准库:允许导入类
import sound_effects.utils # 应用代码:导入模块
from myproject import config # 应用代码:导入模块❌ 错误示例:
python
from myproject.utils import heavy_function # 应用代码:如果存在循环依赖风险,避免直接导入函数Import Formatting
导入格式规范
- Group imports: standard library, third-party, application-specific
- Alphabetize within each group
- Use absolute imports (not relative imports)
- One import per line (except for multiple items from or
typing)collections.abc
python
undefined- 导入分组:标准库、第三方库、应用内代码,三组顺序排列
- 每组内按字母顺序排序
- 使用绝对导入(禁止相对导入)
- 每行仅写一个导入语句(或
typing的多个导入例外)collections.abc
python
undefinedStandard library
标准库
import os
import sys
import os
import sys
Third-party
第三方库
import numpy as np
import tensorflow as tf
import numpy as np
import tensorflow as tf
Application-specific
应用内代码
from myproject.backend import api_utils
undefinedfrom myproject.backend import api_utils
undefinedExceptions
异常(Exceptions)
Use exceptions appropriately. Do not suppress errors with bare clauses.
except:Yes:
python
try:
result = risky_operation()
except ValueError as e:
logging.error(f"Invalid value: {e}")
raiseNo:
python
try:
result = risky_operation()
except: # Too broad, hides bugs
pass合理使用异常,禁止使用空子句掩盖错误。
except:✅ 正确示例:
python
try:
result = risky_operation()
except ValueError as e:
logging.error(f"Invalid value: {e}")
raise❌ 错误示例:
python
try:
result = risky_operation()
except: # 捕获范围过宽,会隐藏bug
passType Annotations
类型注解(Type Annotations)
Annotate all function signatures. Type annotations improve code readability and catch errors early.
General rules:
- Annotate all public APIs
- Use built-in types (,
list,dict) instead ofset, etc. (Python 3.9+)typing.List - Import typing symbols directly:
from typing import Any, Union - Use instead of
Noneortype(None)NoneType
python
def fetch_data(url: str, timeout: int = 30) -> dict[str, Any]:
"""Fetch data from URL."""
...
def process_items(items: list[str]) -> None:
"""Process a list of items."""
...所有函数签名都需要添加类型注解,类型注解可以提升代码可读性,提前发现错误。
通用规则:
- 所有公共API必须添加注解
- Python 3.9+使用内置类型(、
list、dict)替代set等typing.List - 直接导入typing相关符号:
from typing import Any, Union - 使用替代
None或type(None)NoneType
python
def fetch_data(url: str, timeout: int = 30) -> dict[str, Any]:
"""Fetch data from URL."""
...
def process_items(items: list[str]) -> None:
"""Process a list of items."""
...Default Argument Values
默认参数值
Never use mutable objects as default values in function definitions.
Yes:
python
def foo(a: int, b: list[int] | None = None) -> None:
if b is None:
b = []No:
python
def foo(a: int, b: list[int] = []) -> None: # Mutable default - WRONG!
b.append(a)禁止在函数定义中使用可变对象作为默认值。
✅ 正确示例:
python
def foo(a: int, b: list[int] | None = None) -> None:
if b is None:
b = []❌ 错误示例:
python
def foo(a: int, b: list[int] = []) -> None: # 可变默认值,存在严重问题!
b.append(a)True/False Evaluations
布尔值判断
Use implicit false where possible. Empty sequences, , and are false in boolean contexts.
None0Yes:
python
if not users: # Preferred
if not some_dict:
if value:No:
python
if len(users) == 0: # Verbose
if users == []:
if value == True: # Never compare to True/False explicitly尽可能使用隐式假值判断,空序列、、在布尔上下文中均为假值。
None0✅ 正确示例:
python
if not users: # 推荐写法
if not some_dict:
if value:❌ 错误示例:
python
if len(users) == 0: # 写法冗余
if users == []:
if value == True: # 禁止显式和True/False比较Comprehensions & Generators
推导式与生成器
Use comprehensions and generators for simple cases. Keep them readable.
Yes:
python
result = [x for x in data if x > 0]
squares = (x**2 for x in range(10))No:
python
undefined简单场景使用推导式和生成器,注意保持可读性。
✅ 正确示例:
python
result = [x for x in data if x > 0]
squares = (x**2 for x in range(10))❌ 错误示例:
python
undefinedToo complex
逻辑过于复杂,推荐使用普通循环替代
result = [
x.strip().lower() for x in data
if x and len(x) > 5 and not x.startswith('#')
for y in x.split(',') if y
] # Use a regular loop instead
undefinedresult = [
x.strip().lower() for x in data
if x and len(x) > 5 and not x.startswith('#')
for y in x.split(',') if y
]
undefinedLambda Functions
Lambda 函数
Use lambdas for one-liners only. For anything complex, define a proper function.
Yes:
python
sorted(data, key=lambda x: x.timestamp)Acceptable but prefer named function:
python
def get_timestamp(item):
return item.timestamp
sorted(data, key=get_timestamp)仅单行逻辑可以使用lambda,复杂逻辑请定义正式命名函数。
✅ 正确示例:
python
sorted(data, key=lambda x: x.timestamp)可接受但更推荐命名函数的写法:
python
def get_timestamp(item):
return item.timestamp
sorted(data, key=get_timestamp)Style Rules
风格规则
Line Length
行长度
Maximum line length: 88 characters. Exceptions allowed for imports, URLs, and long strings that can't be broken.
最大行长度为88个字符,导入语句、URL、无法拆分的长字符串可不受此限制。
Indentation
缩进
Use 4 spaces per indentation level. Never use tabs.
For hanging indents, align wrapped elements vertically or use 4-space hanging indent:
python
undefined每个缩进层级使用4个空格,禁止使用制表符。
悬挂缩进可垂直对齐包裹元素,或使用4空格悬挂缩进:
python
undefinedAligned with opening delimiter
与起始分隔符对齐
foo = long_function_name(var_one, var_two,
var_three, var_four)
foo = long_function_name(var_one, var_two,
var_three, var_four)
Hanging indent (4 spaces)
4空格悬挂缩进
foo = long_function_name(
var_one, var_two, var_three,
var_four)
undefinedfoo = long_function_name(
var_one, var_two, var_three,
var_four)
undefinedBlank Lines
空行规范
- Two blank lines between top-level definitions
- One blank line between method definitions
- Use blank lines sparingly within functions to show logical sections
- 顶级定义之间空2行
- 方法定义之间空1行
- 函数内部可少量使用空行分隔逻辑块,避免过度使用
Naming Conventions
命名约定
| Type | Convention | Examples |
|---|---|---|
| Packages/Modules | | |
| Classes | | |
| Functions/Methods | | |
| Constants | | |
| Variables | | |
| Private | | |
Avoid:
- Single character names except for counters/iterators (,
i,j)k - Dashes in any name
- (reserved for Python)
__double_leading_and_trailing_underscore__
| 类型 | 规范 | 示例 |
|---|---|---|
| 包/模块 | | |
| 类 | | |
| 函数/方法 | | |
| 常量 | | |
| 变量 | | |
| 私有成员 | | |
禁止用法:
- 除计数器/迭代器(、
i、j)外禁止使用单字符命名k - 任何命名中禁止使用横杠
- 禁止使用格式(Python保留命名格式)
__前后双下划线__
Comments and Docstrings
注释与文档字符串
Docstring Format
文档字符串格式
Use Google-style docstrings for all public modules, functions, classes, and methods.
Function docstring:
python
def fetch_smalltable_rows(
table_handle: smalltable.Table,
keys: Sequence[bytes | str],
require_all_keys: bool = False,
) -> Mapping[bytes, tuple[str, ...]]:
"""Fetches rows from a Smalltable.
Retrieves rows pertaining to the given keys from the Table instance
represented by table_handle. String keys will be UTF-8 encoded.
Args:
table_handle: An open smalltable.Table instance.
keys: A sequence of strings representing the key of each table
row to fetch. String keys will be UTF-8 encoded.
require_all_keys: If True, raise ValueError if any key is missing.
Returns:
A dict mapping keys to the corresponding table row data
fetched. Each row is represented as a tuple of strings.
Raises:
IOError: An error occurred accessing the smalltable.
ValueError: A key is missing and require_all_keys is True.
"""
...Class docstring:
python
class SampleClass:
"""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: bool = False):
"""Initializes the instance based on spam preference.
Args:
likes_spam: Defines if instance exhibits this preference.
"""
self.likes_spam = likes_spam
self.eggs = 0所有公共模块、函数、类、方法都使用Google风格文档字符串。
函数文档字符串示例:
python
def fetch_smalltable_rows(
table_handle: smalltable.Table,
keys: Sequence[bytes | str],
require_all_keys: bool = False,
) -> Mapping[bytes, tuple[str, ...]]:
"""从Smalltable获取行数据。
从table_handle对应的Table实例中检索指定keys对应的行数据,字符串类型的key会被UTF-8编码。
Args:
table_handle: 已打开的smalltable.Table实例。
keys: 要获取的表行key序列,字符串类型的key会被UTF-8编码。
require_all_keys: 若为True,缺失任意key时抛出ValueError。
Returns:
字典类型,key对应获取到的表行数据,每行数据用字符串元组表示。
Raises:
IOError: 访问smalltable时发生错误。
ValueError: require_all_keys为True时存在缺失的key。
"""
...类文档字符串示例:
python
class SampleClass:
"""类的摘要说明。
类的详细说明...
类的详细说明...
Attributes:
likes_spam: 布尔值,表示是否喜欢SPAM。
eggs: 整数,已产出的鸡蛋数量。
"""
def __init__(self, likes_spam: bool = False):
"""根据SPAM偏好初始化实例。
Args:
likes_spam: 定义实例是否存在该偏好。
"""
self.likes_spam = likes_spam
self.eggs = 0Block and Inline Comments
块注释与行内注释
- Use complete sentences with proper capitalization
- Block comments indent to the same level as the code
- Inline comments should be separated by at least 2 spaces
- Use inline comments sparingly
python
undefined- 使用完整句子,首字母大写
- 块注释缩进与对应代码层级一致
- 行内注释与代码之间至少间隔2个空格
- 尽量减少行内注释的使用
python
undefinedBlock comment explaining the following code.
块注释,用于说明下方代码
Can span multiple lines.
可跨行编写
x = x + 1 # Inline comment (use sparingly)
undefinedx = x + 1 # 行内注释(尽量少用)
undefinedStrings
字符串
Use f-strings for formatting (Python 3.6+).
Yes:
python
x = f"name: {name}; score: {score}"Acceptable:
python
x = "name: %s; score: %d" % (name, score)
x = "name: {}; score: {}".format(name, score)No:
python
x = "name: " + name + "; score: " + str(score) # Avoid + for formattingPython 3.6+使用f-string进行格式化。
✅ 正确示例:
python
x = f"name: {name}; score: {score}"可接受写法:
python
x = "name: %s; score: %d" % (name, score)
x = "name: {}; score: {}".format(name, score)❌ 错误示例:
python
x = "name: " + name + "; score: " + str(score) # 禁止使用+拼接做格式化Logging
日志规范
Use Loguru for logging with brace-style lazy formatting:
python
logger.info("Request from {} resulted in {}", ip_address, status_code)Avoid standard with formatting.
logging%使用Loguru进行日志记录,采用大括号风格惰性格式化:
python
logger.info("Request from {} resulted in {}", ip_address, status_code)禁止使用标准库的格式化方式。
logging%Files and Resources
文件与资源
For simple text operations, prefer methods:
pathlibpython
data = Path("file.txt").read_text()
Path("output.txt").write_text("content")For complex operations or non-text files, use context managers:
python
with open("image.png", "rb") as f:
data = f.read()简单文本操作优先使用方法:
pathlibpython
data = Path("file.txt").read_text()
Path("output.txt").write_text("content")复杂操作或非文本文件使用上下文管理器:
python
with open("image.png", "rb") as f:
data = f.read()Statements
语句规范
Generally avoid multiple statements on one line.
Yes:
python
if foo:
bar()No:
python
if foo: bar() # Avoid避免在一行内写多条语句。
✅ 正确示例:
python
if foo:
bar()❌ 错误示例:
python
if foo: bar() # 禁止Main
主函数规范
For executable scripts, use:
python
def main():
...
if __name__ == "__main__":
main()可执行脚本使用如下结构:
python
def main():
...
if __name__ == "__main__":
main()Function Length
函数长度
Keep functions focused and reasonably sized. If a function exceeds about 40 lines, consider splitting it unless it remains very readable.
保持函数职责单一、长度合理。如果函数超过40行,除非可读性极佳,否则建议拆分。
Type Annotation Details
类型注解详情
Forward Declarations
前向声明
Use string quotes for forward references:
python
class MyClass:
def method(self) -> "MyClass":
return self前向引用使用字符串引号包裹:
python
class MyClass:
def method(self) -> "MyClass":
return selfType Aliases
类型别名
Create aliases for complex types:
python
from typing import TypeAlias
ConnectionOptions: TypeAlias = dict[str, str]
Address: TypeAlias = tuple[str, int]
Server: TypeAlias = tuple[Address, ConnectionOptions]为复杂类型创建别名:
python
from typing import TypeAlias
ConnectionOptions: TypeAlias = dict[str, str]
Address: TypeAlias = tuple[str, int]
Server: TypeAlias = tuple[Address, ConnectionOptions]TypeVars
TypeVar
Use descriptive names for TypeVars:
python
from typing import TypeVar
_T = TypeVar("_T") # Good: private, unconstrained
AddableType = TypeVar("AddableType", int, float, str) # Good: descriptiveTypeVar使用描述性命名:
python
from typing import TypeVar
_T = TypeVar("_T") # 推荐:私有、无约束
AddableType = TypeVar("AddableType", int, float, str) # 推荐:命名清晰Generics
泛型
Always specify type parameters for generic types:
Yes:
python
def get_names(employee_ids: list[int]) -> dict[int, str]:
...No:
python
def get_names(employee_ids: list) -> dict: # Missing type parameters
...泛型类型必须指定类型参数:
✅ 正确示例:
python
def get_names(employee_ids: list[int]) -> dict[int, str]:
...❌ 错误示例:
python
def get_names(employee_ids: list) -> dict: # 缺失类型参数
...Imports for Typing
类型相关导入
Import typing symbols directly:
python
from collections.abc import Mapping, Sequence
from typing import Any, Union直接导入typing相关符号:
python
from collections.abc import Mapping, Sequence
from typing import Any, UnionUse built-in types for containers (Python 3.9+)
Python 3.9+容器使用内置类型
def foo(items: list[str]) -> dict[str, int]:
...
undefineddef foo(items: list[str]) -> dict[str, int]:
...
undefinedModern Python Features
现代Python特性
Match Statements (Python 3.10+)
Match 语句(Python 3.10+)
Use structural pattern matching for complex conditionals:
python
def handle_response(response: dict) -> str:
match response:
case {"status": "ok", "data": data}:
return f"Success: {data}"
case {"status": "error", "message": msg}:
return f"Error: {msg}"
case {"status": status}:
return f"Unknown status: {status}"
case _:
return "Invalid response"Pattern matching with types:
python
def process(value: int | str | list) -> str:
match value:
case int(n) if n > 0:
return f"Positive int: {n}"
case int(n):
return f"Non-positive int: {n}"
case str(s):
return f"String: {s}"
case [first, *rest]:
return f"List starting with {first}"复杂条件判断使用结构模式匹配:
python
def handle_response(response: dict) -> str:
match response:
case {"status": "ok", "data": data}:
return f"Success: {data}"
case {"status": "error", "message": msg}:
return f"Error: {msg}"
case {"status": status}:
return f"Unknown status: {status}"
case _:
return "Invalid response"带类型的模式匹配:
python
def process(value: int | str | list) -> str:
match value:
case int(n) if n > 0:
return f"Positive int: {n}"
case int(n):
return f"Non-positive int: {n}"
case str(s):
return f"String: {s}"
case [first, *rest]:
return f"List starting with {first}"Dataclasses with Slots (Python 3.10+)
带Slots的Dataclass(Python 3.10+)
Use for memory efficiency and faster attribute access:
slots=Truepython
from dataclasses import dataclass
@dataclass(slots=True)
class Point:
x: float
y: float
@dataclass(slots=True, frozen=True)
class ImmutableConfig:
host: str
port: int
timeout: float = 30.0使用提升内存效率,加快属性访问速度:
slots=Truepython
from dataclasses import dataclass
@dataclass(slots=True)
class Point:
x: float
y: float
@dataclass(slots=True, frozen=True)
class ImmutableConfig:
host: str
port: int
timeout: float = 30.0Postponed Annotation Evaluation
延后注解求值
Use for:
from __future__ import annotations- Forward references without quotes
- Faster module import (annotations not evaluated at definition time)
python
from __future__ import annotations
class Node:
def __init__(self, children: list[Node]) -> None: # No quotes needed
self.children = children
def add_child(self, child: Node) -> None:
self.children.append(child)使用可实现:
from __future__ import annotations- 无需引号即可使用前向引用
- 模块导入速度更快(注解不会在定义时求值)
python
from __future__ import annotations
class Node:
def __init__(self, children: list[Node]) -> None: # 无需引号
self.children = children
def add_child(self, child: Node) -> None:
self.children.append(child)Exception Groups (Python 3.11+)
异常组(Python 3.11+)
Handle multiple exceptions simultaneously:
python
try:
async with asyncio.TaskGroup() as tg:
tg.create_task(task1())
tg.create_task(task2())
except* ValueError as eg:
for exc in eg.exceptions:
logger.error("ValueError: {}", exc)
except* TypeError as eg:
for exc in eg.exceptions:
logger.error("TypeError: {}", exc)同时处理多个异常:
python
try:
async with asyncio.TaskGroup() as tg:
tg.create_task(task1())
tg.create_task(task2())
except* ValueError as eg:
for exc in eg.exceptions:
logger.error("ValueError: {}", exc)
except* TypeError as eg:
for exc in eg.exceptions:
logger.error("TypeError: {}", exc)Common Patterns
常用模式
Properties
属性(Properties)
Use properties for simple attribute access:
python
class Square:
def __init__(self, side: float):
self._side = side
@property
def area(self) -> float:
return self._side ** 2简单属性访问使用property:
python
class Square:
def __init__(self, side: float):
self._side = side
@property
def area(self) -> float:
return self._side ** 2Conditional Expressions
条件表达式
Use ternary operators for simple conditions:
python
x = "yes" if condition else "no"简单条件使用三元运算符:
python
x = "yes" if condition else "no"Context Managers
上下文管理器
Create custom context managers when appropriate:
python
from contextlib import contextmanager
@contextmanager
def managed_resource(*args, **kwargs):
resource = acquire_resource(*args, **kwargs)
try:
yield resource
finally:
release_resource(resource)合适场景下创建自定义上下文管理器:
python
from contextlib import contextmanager
@contextmanager
def managed_resource(*args, **kwargs):
resource = acquire_resource(*args, **kwargs)
try:
yield resource
finally:
release_resource(resource)Linting
代码检查(Linting)
Run on all Python code. Suppress warnings only when necessary:
ruffpython
dict = 'something' # noqa: A001所有Python代码都要运行检查,仅必要时抑制警告:
ruffpython
dict = 'something' # noqa: A001Package __init__.py
Files
__init__.py包__init__.py
文件规范
__init__.pyTHERE MUST BE NO CODE IN FILES. Keep them empty.
__init__.pypython
undefined__init__.pypython
undefinedinit.py
init.py
This file should be empty
本文件应保持为空
Import from modules directly:
```python
直接从模块导入所需内容:
```pythonInstead of: from mypackage import MyClass
不推荐:from mypackage import MyClass
Use: from mypackage.core import MyClass
推荐:from mypackage.core import MyClass
undefinedundefinedPreferred Libraries
推荐库
Use these libraries when applicable:
| Purpose | Library |
|---|---|
| Data validation/models | |
| Logging | |
| CLI | |
| Testing | |
对应场景优先使用以下库:
| 用途 | 库 |
|---|---|
| 数据校验/模型 | |
| 日志 | |
| CLI | |
| 测试 | |
Summary
总结
When writing Python code:
- Use type annotations for all functions
- Follow naming conventions consistently
- Write clear docstrings for all public APIs
- Keep functions focused and reasonably sized
- Use comprehensions for simple cases
- Prefer implicit false in boolean contexts
- Use f-strings for formatting
- Always use context managers for resources
- Run and
ruff checkruff format - Keep files empty
__init__.py - BE CONSISTENT with existing code
编写Python代码时遵循以下规则:
- 所有函数添加类型注解
- 严格遵循命名约定
- 所有公共API编写清晰的文档字符串
- 保持函数职责单一、长度合理
- 简单场景使用推导式
- 布尔判断优先使用隐式假值
- 使用f-string做字符串格式化
- 资源操作始终使用上下文管理器
- 运行和
ruff checkruff format - 保持文件为空
__init__.py - 与现有代码保持一致性
Additional Resources
额外资源
For detailed reference on specific topics, see:
- references/advanced_types.md - Advanced type annotation patterns including Protocol, TypedDict, Literal, ParamSpec, and more
- references/antipatterns.md - Common Python mistakes and their fixes
- references/docstring_examples.md - Comprehensive docstring examples for all Python constructs
特定主题的详细参考可查看:
- references/advanced_types.md - 高级类型注解模式,包括Protocol、TypedDict、Literal、ParamSpec等
- references/antipatterns.md - Python常见错误及修复方案
- references/docstring_examples.md - 所有Python结构的完整文档字符串示例