ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MMCV 代码规范完整指南:PEP 8、命名、docstring、类型注解与 pre-commit 落地实践

MMCV 代码规范完整指南:PEP 8、命名、docstring、类型注解与 pre-commit 落地实践 人工智能计算机视觉深度学习【免费下载链接】mmcvOpenMMLab Computer Vision Foundation项目地址https://gitcode.com/gh_mirrors/mm/mmcv点击查看免费下载本文是 OpenMMLab 计算机视觉基础库 MMCV 的代码风格官方指南对应仓库文档 docs/zh_cn/community/code_style.md的深度展开版。它面向两类读者一是准备向 MMCV 提交 Pull Request 的贡献者需要让代码通过 pre-commit、CI 与 reviewer 的审查二是希望在项目内建立统一代码规范的团队。读完本文你将掌握 MMCV 所遵循的 PEP 8 与 Google 风格取舍、命名与 docstring 的具体写法、类型注解与 mypy 的使用方法以及 pre-commit 工具链的完整配置从而写出与仓库风格一致、可维护、易审查的 Python 代码。一、代码规范的两个标准与 MMCV 的取舍1.1 PEP 8 —— Python 官方代码规范PEP 8 是 Python 官方的代码风格指南是 OpenMMLab 算法库首选的代码规范见 docs/zh_cn/community/contributing.md 中代码风格一节。它主要覆盖以下几方面内容代码布局规定 Python 中空行、断行以及导入相关的风格。一个常见疑问是当代码较长无法在一行内写完时何处可以断行PEP 8 给出了明确的换行规则。表达式规定表达式中空格的使用方式。尾随逗号当列表较长、无法一行写下而写成逐行列表时推荐在末项之后也加上逗号便于后续追加选项和版本控制对比。尾随逗号的正反例# Correct: FILES [setup.cfg, tox.ini] # Correct: FILES [ setup.cfg, tox.ini, ] # Wrong: FILES [setup.cfg, tox.ini,] # Wrong: FILES [ setup.cfg, tox.ini ]命名、注释、类型注解这些内容的详细规范是本文后续章节的主体。1.2 项目内一致性优先于 PEP 8A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is the most important.PEP 8 的规范并不是绝对的项目内的一致性要优先于 PEP 8 的规范。OpenMMLab 各个项目都在setup.cfg中设定了代码规范设置贡献者应遵照这些设置。例如 PEP 8 中有如下例子# Correct: hypot2 x*x y*y # Wrong: hypot2 x * x y * y这一规范本意是指示运算优先级但 OpenMMLab 的设置中通常没有启用 yapf 的ARITHMETIC_PRECEDENCE_INDICATION选项因而格式规范工具不会按照该推荐样式强制格式化一切以项目实际配置为准。打开仓库根目录的 setup.cfg 可以看到[yapf] based_on_style pep8 blank_line_before_nested_class_or_def true split_before_expression_after_opening_paren true [isort] line_length 79 multi_line_output 0 extra_standard_library pkg_resources,setuptools,logging,os,warnings,abc known_first_party mmcv known_third_party addict,cv2,matplotlib,numpy,onnx,packaging,pytest,pytorch_sphinx_theme,scipy,sphinx,torch,torchvision,yaml,yapf no_lines_before STDLIB,LOCALFOLDER default_section THIRDPARTY这些配置说明yapf 基于 pep8 风格isort 的每行长度限制为 79 字符mmcv被标记为 first party而 torch、numpy 等被标记为 third party导入顺序会自动按标准库 → 第三方 → 本地模块排列。1.3 Google 开源项目风格指南Google 开源项目风格指南Google Python Style Guide比 PEP 8 提供了更详尽的指导包含语言规范和风格规范两个部分语言规范对 Python 中许多语言特性异常、Lambda 表达式、列表推导式、metaclass 等进行优缺点分析并给出使用意见。风格规范大部分约定建立在 PEP 8 基础上同时有更细的约定如函数长度、TODO 注释、文件与 socket 对象的访问等。MMCV 推荐将 Google 指南作为开发参考但不必严格遵照原因有二该指南存在 Python 2 兼容需求例如要求所有无基类的类显式继承object而在仅使用 Python 3 的环境中这一要求不必要按本项目惯例即可OpenMMLab 项目作为框架级开源软件不必对高级技巧过于避讳尤其是 MMCV但使用这些技巧前应认真考虑是否真的有必要并寻求其他开发者的广泛评估。需要特别留意的一处差异是包的导入Google 指南要求导入本地包时使用路径全称且每个模块单独成行。这在 MMCV 中通常不必要也不符合项目开发惯例本项目约定如下# Correct from mmcv.cnn.bricks import (Conv2d, build_norm_layer, DropPath, MaxPool2d, Linear) from ..utils import ext_loader # Wrong from mmcv.cnn.bricks import Conv2d, build_norm_layer, DropPath, MaxPool2d, \ Linear # 使用括号进行连接而不是反斜杠 from ...utils import is_str # 最多向上回溯一层过多的回溯容易导致结构混乱要点跨行导入用括号连接而非反斜杠相对导入最多向上回溯一层避免结构混乱。1.4 OpenMMLab 的落地pre-commit 自动格式化OpenMMLab 项目使用 pre-commit 工具自动格式化代码具体安装与使用见 docs/zh_cn/community/contributing.md 的配置 pre-commit与代码风格章节。核心命令如下须在 MMCV 目录下执行pip install -U pre-commit pre-commit install pre-commit run --all-files中国用户若因网络问题安装失败可使用国内镜像配置pre-commit install -c .pre-commit-config-zh-cn.yaml pre-commit run --all-files -c .pre-commit-config-zh-cn.yaml仓库根目录的 .pre-commit-config.yaml 是本项目实际的钩子配置包含以下工具链钩子作用flake8Python 官方推荐的代码规范检查工具是多个检查工具的封装isort自动调整模块导入顺序yapfGoogle 发布的代码格式化工具trailing-whitespace / mixed-line-ending / end-of-file-fixer去除行尾空白、统一行尾符LF、修复文件末尾换行check-yaml / check-merge-conflict校验 YAML 语法、检查未解决的合并冲突requirements-txt-fixer调整requirements.txt中包的顺序double-quote-string-fixer / fix-encoding-pragma / pyupgrade统一引号、移除编码声明、升级为 Python 3 语法codespell检查单词拼写mdformat检查并格式化 Markdown 文件配合 mdformat-openmmlabdocformatter格式化 docstring--in-place --wrap-descriptions 79check-copyright检查文件版权头针对 mmcv、tests排除 mmcv/opsmypy静态类型检查排除 tests 与 docs 目录其中 C 和 CUDA 代码遵循 Google C Style Guideclang-format 钩子在配置中以注释形式预留。如果提交的代码不符合代码风格规范pre-commit 会发出警告并自动修复部分错误若想临时绕开检查可在git commit时加上--no-verify仅用于临时提交最终推送的代码必须通过 pre-commit 检查。二、命名规范2.1 命名规范的重要性优秀的命名是良好代码可读性的基础。基础命名规范对各类变量做约束使读者能根据名字判断它是一个类、局部变量还是全局变量而优秀的命名则要求作者对变量功能有清晰认识与良好表达能力让读者仅凭名称即可理解其含义。2.2 基础命名规范类型公有私有模块lower_with_under_lower_with_under包lower_with_under类CapWords_CapWords异常CapWordsError函数方法lower_with_under_lower_with_under函数 / 方法参数lower_with_under全局 / 类内常量CAPS_WITH_UNDER_CAPS_WITH_UNDER全局 / 类内变量lower_with_under_lower_with_under变量lower_with_under_lower_with_under局部变量lower_with_under注意尽量避免变量名与保留字冲突若不可避免可使用一个后置下划线如class_尽量不要使用过于简单的命名约定俗成的循环变量i、文件变量f、错误变量e除外不会被用到的变量可命名为_逻辑检查器会将其忽略。2.3 命名技巧良好的变量命名需保证三点含义准确、没有歧义长短适中前后统一。# Wrong class Masks(metaclassABCMeta): # 命名无法表现基类Instance or Semantic pass # Correct class BaseInstanceMasks(metaclassABCMeta): pass # Wrong不同地方含义相同的变量尽量用统一的命名 def __init__(self, inplanes, planes): pass def __init__(self, in_channels, out_channels): pass常见的函数命名方法动宾命名法crop_img,init_weights动宾倒置命名法imread,bbox_flip注意函数命名与参数的顺序保证主语在前、符合语言习惯check_keys_exist(key, container)check_keys_contain(container, key)还要避免非常规或未统一约定的缩写如nb→num_blocksin_nc→in_channels。三、docstring 规范3.1 为什么要写 docstringdocstring 是对一个类、一个函数功能与 API 接口的详细描述有两个功能帮助其他开发者了解代码功能方便 debug 和复用代码在 Readthedocs 文档中自动生成相关 API reference 文档帮助不了解源代码的社区用户使用功能。3.2 如何写 docstring与普通注释不同规范的 docstring 有严格的格式要求以便 Python 解释器与 sphinx 进行文档解析docstring 的基本约定见 PEP 257。MMCV 参考格式为 Google 风格同时结合了 OpenMMLab 自身惯例。以下按模块、类、方法三种场景给出标准格式。1. 模块文档代码风格规范推荐为每个模块Python 文件编写 docstring但目前 OpenMMLab 项目大部分没有此类 docstring因此不做硬性要求。参考格式A one line summary of the module or program, terminated by a period. Leave one blank line. The rest of this docstring should contain an overall description of the module or program. Optionally, it may also contain a brief description of exported classes and functions and/or usage examples. Typical usage example: foo ClassFoo() bar foo.FunctionBar() 2. 类文档类文档是贡献者最常编写的类型。按照 OpenMMLab 惯例这里使用了与 Google 风格不同的写法不使用 Attributes 描述类属性而是使用 Args 描述__init__函数的参数。Args 中遵照parameter (type): Description.格式描述每个参数的类型与功能多种类型可用(float or str)写法可以为 None 的参数写为(int, optional)。class BaseRunner(metaclassABCMeta): The base class of Runner, a training helper for PyTorch. All subclasses should implement the following APIs: - run() - train() - val() - save_checkpoint() Args: model (:obj:torch.nn.Module): The model to be run. batch_processor (callable, optional): A callable method that process a data batch. The interface of this method should be batch_processor(model, data, train_mode) - dict. Defaults to None. optimizer (dict or :obj:torch.optim.Optimizer, optional): It can be either an optimizer (in most cases) or a dict of optimizers (in models that requires more than one optimizer, e.g., GAN). Defaults to None. work_dir (str, optional): The working directory to save checkpoints and logs. Defaults to None. logger (:obj:logging.Logger): Logger used during training. Defaults to None. (The default value is just for backward compatibility) meta (dict, optional): A dict records some import information such as environment info and seed, which will be logged in logger hook. Defaults to None. max_epochs (int, optional): Total training epochs. Defaults to None. max_iters (int, optional): Total training iterations. Defaults to None. def __init__(self, model, batch_processorNone, optimizerNone, work_dirNone, loggerNone, metaNone, max_itersNone, max_epochsNone): ...补充要求在算法实现的主体类中建议加入原论文链接如果参考了其他开源代码实现应加入modified from直接复制了其他代码库实现则应加入copied from并注意源码的 License如有必要可通过.. math::加入数学公式。# 参考实现 # This func is modified from detectron2 # ..._. # 复制代码 # This code was copied from the ubelt # library..._. # 引用论文 添加公式 class LabelSmoothLoss(nn.Module): rInitializer for the label smoothed cross entropy loss. Refers to Rethinking the Inception Architecture for Computer Vision ..._. This decreases gap between output scores and encourages generalization. Labels provided to forward can be one-hot like vectors (NxC) or class indices (Nx1). And this accepts linear combination of one-hot like labels from mixup or cutmix except multi-label task. Args: label_smooth_val (float): The degree of label smoothing. num_classes (int, optional): Number of classes. Defaults to None. mode (str): Refers to notes, Options are original, classy_vision, multi_label. Defaults to classy_vision. reduction (str): The method used to reduce the loss. Options are none, mean and sum. Defaults to mean. loss_weight (float): Weight of the loss. Defaults to 1.0. Note: if the mode is original, this will use the same label smooth method as the original paper as: .. math:: (1-\epsilon)\delta_{k, y} \frac{\epsilon}{K} where :math:\epsilon is the label_smooth_val, :math:K is the num_classes and :math:\delta_{k,y} is Dirac delta, which equals 1 for ky and 0 otherwise. if the mode is classy_vision, this will use the same label smooth method as the facebookresearch/ClassyVision ..._ repo as: .. math:: \frac{\delta_{k, y} \epsilon/K}{1\epsilon} if the mode is multi_label, this will accept labels from multi-label task and smoothing them as: .. math:: (1-2\epsilon)\delta_{k, y} \epsilon 注意 reStructuredText 中三种引号功能不同here双反引号表示一段代码here单反引号表示斜体here双引号无特殊含义一般表示字符串。其中单反引号的用法与 Markdown 不同需要多加留意。另外还有:obj:type 这种更规范的表示类的写法鉴于长度不做特别要求一般仅用于表示非常用类型。3. 方法函数文档函数文档与类文档结构基本一致但需要加入返回值文档。对于较复杂的函数和类可使用Examples字段加入示例如果需要给参数加入较长备注可加入Note字段。示例最好能直接在 Python 交互式环境中运行并给出对应结果多个示例可用注释分隔说明。def import_modules_from_strings(imports, allow_failed_importsFalse): Import modules from the given list of strings. Args: imports (list | str | None): The given module names to be imported. allow_failed_imports (bool): If True, the failed imports will return None. Otherwise, an ImportError is raise. Defaults to False. Returns: List[module] | module | None: The imported modules. All these three lines in docstring will be compiled into the same line in readthedocs. Examples: osp, sys import_modules_from_strings( ... [os.path, sys]) import os.path as osp_ import sys as sys_ assert osp osp_ assert sys sys_ ...如果函数接口在某个版本发生了变化需要在 docstring 中加入说明必要时添加Note或Warningclass CheckpointHook(Hook): Save checkpoints periodically. Args: out_dir (str, optional): The root directory to save checkpoints. If not specified, runner.work_dir will be used by default. If specified, the out_dir will be the concatenation of out_dir and the last level directory of runner.work_dir. Defaults to None. Changed in version 1.3.15. file_client_args (dict, optional): Arguments to instantiate a FileClient. See :class:mmcv.fileio.FileClient for details. Defaults to None. New in version 1.3.15. Warning: Before v1.3.15, the out_dir argument indicates the path where the checkpoint is stored. However, in v1.3.15 and later, out_dir indicates the root directory and the final path to save checkpoint is the concatenation of out_dir and the last level directory of runner.work_dir. Suppose the value of out_dir is /path/of/A and the value of runner.work_dir is /path/of/B, then the final path will be /path/of/A/B. 如果参数或返回值里带有需要展开描述字段的 dict应采用如下格式def func(x): r Args: x (None): A dict with 2 keys, padded_targets, and targets. - targets (list[Tensor]): A list of tensors. Each tensor has the shape of :math:(T_i). Each element is the index of a character. - padded_targets (Tensor): A tensor of shape :math:(N). Each item is the length of a word. Returns: dict: A dict with 2 keys, padded_targets, and targets. - targets (list[Tensor]): A list of tensors. Each tensor has the shape of :math:(T_i). Each element is the index of a character. - padded_targets (Tensor): A tensor of shape :math:(N). Each item is the length of a word. return x3.3 docstring 与 readthedocs 渲染为了生成 readthedocs 文档docstring 需要按照 reStructuredText 文档格式编写否则会产生文档渲染错误。在提交 PR 前最好生成并预览文档效果方法见 docs/zh_cn/community/contributing.md 的文档渲染指引pip install -r requirements/docs.txt cd docs/zh_cn/ # or docs/en make html # check file in ./docs/zh_cn/_build/html/index.html语法规范参考 reStructuredText PrimerSphinx 官方文档与 Example Google Style Python Docstringssphinxcontrib-napoleon 文档。OpenMMLab 使用 pytorch_sphinx_theme 与 napoleon 扩展见 requirements/docs.txt 与 docs/zh_cn/conf.py将上述 Google 风格的 docstring 自动渲染为 API reference 页面如 docs/zh_cn/api/ 下各模块的 .rst 文件。四、注释规范4.1 为什么要写注释对于一个开源项目团队合作以及社区之间的合作必不可少因此尤其要重视合理注释。不写注释的代码可能过几个月连作者自己也难以理解造成额外的阅读和修改成本。4.2 如何写注释最需要写注释的是代码中技巧性的部分。如果你在下次代码审查的时候必须解释一下那么你应该现在就给它写注释。对于复杂的操作应该在其操作开始前写上若干行注释对于不是一目了然的代码应在其行尾添加注释。Google 开源项目风格指南# 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 if i is 0 or a power of 2.两条硬性规则为了提高可读性注释应至少离开代码2 个空格绝不要描述代码。假设阅读代码的人比你更懂 Python他只是不知道你的代码要做什么。Google 开源项目风格指南# Wrong: # Now go through the b array and make sure whenever i occurs # the next element is i1 # Wrong: if i (i-1) 0: # True if i bitwise and i-1 is 0.在注释中可以使用 Markdown 语法开发人员通常熟悉 Markdown便于交流理解如用单反引号表示代码和变量——注意不要与 docstring 中的 reStructuredText 语法混淆# _reversed_padding_repeated_twice is the padding to be passed to # F.pad if needed (e.g., for non-zero padding types that are # implemented as two ops: padding conv). F.pad accepts paddings in # reverse order than the dimension. self._reversed_padding_repeated_twice _reverse_repeat_tuple(self.padding, 2)4.3 注释示例代码风格文档给出了两类典型注释场景复杂逻辑结构对优先级关系进行说明。例如 registry 构建函数的选择逻辑# self.build_func will be set with the following priority: # 1. build_func # 2. parent.build_func # 3. build_from_cfg if build_func is None: if parent is not None: self.build_func parent.build_func else: self.build_func build_from_cfg else: self.build_func build_funcbug 修复的特殊处理附带相关 issue 链接帮助其他人了解 bug 背景。例如 checkpoint 保存时针对 PyTorch 1.6 文件格式变更的兼容处理def _save_ckpt(checkpoint, file): # The 1.6 release of PyTorch switched torch.save to use a new # zipfile-based file format. It will cause RuntimeError when a # checkpoint was saved in high version (PyTorch version1.6.0) but # loaded in low version (PyTorch version1.6.0). More details at # https://github.com/open-mmlab/mmpose/issues/904 if digit_version(TORCH_VERSION) digit_version(1.6.0): torch.save(checkpoint, file, _use_new_zipfile_serializationFalse) else: torch.save(checkpoint, file)五、类型注解5.1 为什么要写类型注解类型注解是对函数中变量的类型做限定或提示为代码的安全性提供保障、增强可读性、避免出现类型相关的错误。Python 对类型没有强制限制类型注解只起提示作用IDE 会解析注解并在调用代码时给出类型提示类型注解检查工具如 mypy则会根据注解对代码中可能出现的问题进行检查减少 bug 的出现。通常不需要注释模块中的所有函数按以下原则权衡公共的 API 需要注释在代码的安全性、清晰性和灵活性之间权衡是否注释对于容易出现类型相关错误的代码进行注释难以理解的代码请进行注释若代码中的类型已经稳定可以进行注释。对于一份成熟的代码多数情况下即使注释了所有函数也不会丧失太多灵活性。5.2 函数 / 方法类型注解通常不对self和cls注释。根据行宽有多种写法from typing import Optional, List, Tuple # 全部位于一行 def my_method(self, first_var: int) - int: pass # 另起一行 def my_method( self, first_var: int, second_var: float) - Tuple[MyLongType1, MyLongType1, MyLongType1]: pass # 单独成行具体的应用场合与行宽有关建议结合 yapf 自动化格式使用 def my_method( self, first_var: int, second_var: float ) - Tuple[MyLongType1, MyLongType1, MyLongType1]: pass # 引用尚未被定义的类型 class MyClass: def __init__(self, stack: List[MyClass]) - None: pass类型注解中的类型可以是 Python 内置类型、自定义类也可以使用typing提供的 wrapper 类进行装饰。常用注解# 数值类型 from numbers import Number # 可选类型指参数可以为 None from typing import Optional def foo(var: Optional[int] None): pass # 联合类型指同时接受多种类型 from typing import Union def foo(var: Union[float, str]): pass from typing import Sequence # 序列类型 from typing import Iterable # 可迭代类型 from typing import Any # 任意类型 from typing import Callable # 可调用类型 from typing import List, Dict # 列表和字典的泛型类型 from typing import Tuple # 元组的特殊格式 # 虽然在 Python 3.9 中list, tuple 和 dict 本身已支持泛型但为了支持之前的版本 # 我们在进行类型注解时还是需要使用 List, Tuple, Dict 类型 # 另外在对参数类型进行注解时尽量使用 Sequence Iterable Mapping # List, Tuple, Dict 主要用于返回值类型注解5.3 变量类型注解一般用于难以直接推断类型时# Recommend: 带类型注解的赋值 a: Foo SomeUndecoratedFunction() a: List[int]: [1, 2, 3] # List 只支持单一类型泛型可使用 Union b: Tuple[int, int] (1, 2) # 长度固定为 2 c: Tuple[int, ...] (1, 2, 3) # 变长 d: Dict[str, int] {a: 1, b: 2} # Not Recommend行尾类型注释 # 虽然这种方式被写在了 Google 开源指南中但这是一种为了支持 Python 2.7 版本 # 而补充的注释方式鉴于我们只支持 Python 3, 为了风格统一不推荐使用这种方式。 a SomeUndecoratedFunction() # type: Foo a [1, 2, 3] # type: List[int] b (1, 2, 3) # type: Tuple[int, ...] c (1, 2, 3.5) # type: Tuple[int, Text, float]5.4 自定义泛型除了使用typing内置的List、Dict泛型也可以利用TypeVar和Generic定义自己的泛型from typing import TypeVar, Generic KT TypeVar(KT) VT TypeVar(VT) class Mapping(Generic[KT, VT]): def __init__(self, data: Dict[KT, VT]): self._data data def __getitem__(self, key: KT) - VT: return self._data[key]使用上述方法定义了一个拥有泛型能力的映射类mapping Mappingstr, float value: float example[a]另外可以利用TypeVar在函数签名中指定联动的多个类型from typing import TypeVar, List T TypeVar(T) # Can be anything A TypeVar(A, str, bytes) # Must be str or bytes def repeat(x: T, n: int) - List[T]: Return a list containing n references to x. return [x]*n def longest(x: A, y: A) - A: Return the longest of two strings. return x if len(x) len(y) else y5.5 mypy类型注解检查工具mypy 是一个 Python 静态类型检查工具。它会根据类型注解检查传参、赋值等操作是否符合注解从而避免可能出现的 bug。考虑如下脚本test.pydef foo(var: int) - float: return float(var) a: str foo(2.0) b: int foo(3.0) # type: ignore运行mypy test.py得到test.py:4: error: Incompatible types in assignment (expression has type float, variable has type int) test.py:4: error: Argument 1 to foo has incompatible type str; expected int Found 2 errors in 1 file (checked 1 source file)输出分别指出了第 4 行在函数调用参数和返回值赋值两处的类型错误第 5 行同样存在两处类型错误但因为使用了type: ignore而被忽略——只有部分特殊情况才需要此类忽略。MMCV 在提交代码时要求补充类型注解并通过 mypy 检查mypy 钩子已配置在 .pre-commit-config.yaml 中排除了 tests 与 docs 目录。六、提交 PR 前的代码规范自查清单结合 docs/zh_cn/community/contributing.md 与 docs/zh_cn/community/pr.md向 MMCV 提交代码前应完成以下检查pre-commit 检查在 MMCV 目录下执行pre-commit run --all-files确保 flake8、yapf、isort、mdformat、docformatter、codespell、mypy 等钩子全部通过若钩子安装被网络中断可重复执行pre-commit run ...继续安装单元测试pytest tests通过全量测试至少保证修改模块的测试通过例如pytest tests/test_utils/test_env.py可用python -m coverage run -m pytest /path/to/test_file python -m coverage html检查覆盖率查看htmlcov/index.html文档渲染若修改/新增了 docstring 或文档安装pip install -r requirements/docs.txt后在docs/zh_cn/或docs/en/下执行make html确认 reStructuredText 语法渲染无误检查docs/zh_cn/_build/html/index.html代码风格Python 遵循 PEP 8 并遵循本文全部规范C 与 CUDA 遵循 Google C Style GuidePR 粒度与描述一个 PR 只做一件事粒度要细标题格式为[Prefix] Short description (Suffix)前缀包括[Feature]新功能、[Fix]修 bug、[Docs]文档、[WIP]开发中描述中说明修改理由、修改内容与影响并关联相关 Issue。遵守这套规范既能保证你的代码与 MMCV 现有代码库高度一致也能让代码在 Readthedocs 上正确渲染为 API 文档惠及所有社区用户。赞分享人工智能计算机视觉深度学习【免费下载链接】mmcvOpenMMLab Computer Vision Foundation项目地址https://gitcode.com/gh_mirrors/mm/mmcv点击查看免费下载相关推荐QUANTAXIS Python 代码规范完全指南PEP 8、类型注解、命名规范与质量工具实战QUANTAXIS Python 代码规范完全指南PEP 8、类型注解、命名规范与质量工具实战 本文依据仓库文档 doc/development/code s金融科技后端数据分析DeepChem 开发规范指南从 pre-commit 到类型注解的完整代码质量保障体系DeepChem 开发规范指南从 pre commit 到类型注解的完整代码质量保障体系 本篇技术指南以 DeepChem 官方开发文档中的 Coding C人工智能深度学习机器学习生物信息学科学计算Python 3编码规范与最佳实践PEP 8完全解读指南Python 3编码规范与最佳实践PEP 8完全解读指南 想要写出专业、易读且符合行业标准的Python代码吗掌握PEP 8编码规范是每个Python开发者文档教程上一篇告别气候数据处理困境用sqlx构建高效验证案例数据库下一篇gh_mirrors/ove/overleaf代码审查流程PR规范与自动化检查创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表