# PaddleRS代码注释规范

## 1 注释规范

函数的docstring由5个模块构成:

- 函数功能描述;
- 函数参数;
- (可选)函数返回值;
- (可选)函数可能抛出的异常;
- (可选)使用示例。

类的docstring也由5个模块构成:

- 类功能描述;
- 实例化类所需参数;
- (可选)实例化类得到的对象;
- (可选)实例化类时可能抛出的异常;
- (可选)使用示例。

以下将详细叙述每个模块的规范。

### 1.1 函数/类功能描述

目标是让用户能快速看懂。该模块又可以拆解为3个部分,功能叙述 + 计算公式 + 注解。

- 功能叙述:描述该函数或类的具体功能。由于用户不一定具有相应背景知识,所以需要补充必要的细节。
- (可选)计算公式:如有需要,给出函数的计算公式。公式建议以LaTex文法编写。
- (可选)注解:如需要特殊说明,可以在该部分给出。

示例:

```python
"""
    Add two tensors element-wise. The equation is:

        out = x + y

    Note: This function supports broadcasting. If you want know more about broadcasting, please
        refer to :ref:`user_guide_broadcasting` .
"""
```

### 1.2 函数参数/类构造参数

要解释清楚每个参数的**类型**、**含义**和**默认值**(如果有)。

注意事项:

- 可选参数要备注`optional`,例如:`name (str|None, optinoal)`;
- 若参数具有多种可选类型,用`|`分隔;
- 参数名和类型之间需要空1格;
- 可使用`list[{类型名}]`和`tuple[{类型名}]`的方式表示包含某种类型对象的列表或元组(注意大小写),例如`list[int]`表示包含`int`类型元素的列表,`tuple[int|float]`等价于`tuple[int] | tuple[float]`;
- 使用`list[{类型名}]`和`tuple[{类型名}]`的描述时,默认假设列表或元组参数为同质的(即其中包含的所有元素具有相同的类型),若允许或需要列表、元组参数为异质的,需要在文字描述中说明;
- 被分隔的类型如果是简单类型如`int`、`Tensor`等则`|`前后不需要添加空格,如果是多个复杂类型如`list[int]`和`tuple[float]`则需要在`|`前后添加空格;
- 对于有默认值的参数,至少要讲清楚在取默认值时的逻辑,而不仅仅是介绍这个参数是什么以及默认值是什么。

示例:

```python
"""
    Args:
        x (Tensor|np.ndarray): Input tensor or numpy array.
        points (list[int] | tuple[int|float]): List or tuple of data points.
        name (str|None, optional): Name for the operation. If None, the operation will not be named.
            Default: None.
"""
```

### 1.3 返回值/构造对象

对于函数返回值,先描述返回值的类型(用`(``)`包围,语法与参数类型描述一致),然后说明返回值的含义。对于实例化类得到的对象,无需说明类型。

示例1:

```python
"""
    Returns:
        (tuple): When label is None, it returns (im, im_info); otherwise it returns (im, im_info, label).
"""
```

示例2:

```python
"""
    Returns:
        (N-D Tensor): A location into which the result is stored.
"""
```

示例3(类定义中):

```python
"""
    Returns:
        A callable object of Activation.
"""
```

### 1.4 可能抛出的异常

需给出异常类型和抛出异常的条件。

示例:

```python
"""
    Raises:
        ValueError: When memory() is called outside block().
        TypeError: When init is set and is not a Variable.
"""
```

### 1.5 使用示例

为函数或类的各种使用场景尽可能地提供示例,并在注释中给出执行代码预期得到的结果。

要求:用户复制示例代码到脚本即可运行。注意需要加必要的`import`。

单example示例:

```python
"""
    Examples:

            import paddle
            import numpy as np

            paddle.enable_imperative()
            np_x = np.array([2, 3, 4]).astype('float64')
            np_y = np.array([1, 5, 2]).astype('float64')
            x = paddle.imperative.to_variable(np_x)
            y = paddle.imperative.to_variable(np_y)

            z = paddle.add(x, y)
            np_z = z.numpy()
            # [3., 8., 6. ]

            z = paddle.add(x, y, alpha=10)
            np_z = z.numpy()
            # [12., 53., 24. ]
"""
```

多examples示例:

```python
"""
    Examples 1:

        from paddleseg.cvlibs.manager import ComponentManager

        model_manager = ComponentManager()

        class AlexNet: ...
        class ResNet: ...

        model_manager.add_component(AlexNet)
        model_manager.add_component(ResNet)

        # Alternatively, pass a sequence:
        model_manager.add_component([AlexNet, ResNet])
        print(model_manager.components_dict)
        # {'AlexNet': <class '__main__.AlexNet'>, 'ResNet': <class '__main__.ResNet'>}

    Examples 2:

        # Use it as a Python decorator.
        from paddleseg.cvlibs.manager import ComponentManager

        model_manager = ComponentManager()

        @model_manager.add_component
        class AlexNet: ...

        @model_manager.add_component
        class ResNet: ...

        print(model_manager.components_dict)
        # {'AlexNet': <class '__main__.AlexNet'>, 'ResNet': <class '__main__.ResNet'>}
"""
```

### 1.6 语法

- 措词准确,使用深度学习领域通用的词汇和说法。
- 语句通顺,符合英文语法。
- 文档中对同一事物的表述要做到前后一致,比如避免有时用label、有时用ground truth。

### 1.7 其他注意事项

- 不同模块间以**1**个空行分隔。
- 注意首字母大写以及添加标点符号(尤其是**句号**),符合英语语法规则。
- 在代码示例内容中可适当加空行以体现层次感。
- 对于注释中出现的**输入参数名**、**输入参数的属性或方法**以及**文件路径**,使用反引号`\``包围。
- 每个模块的标题/子标题和具体内容之间需要有换行和缩进,`Examples:`标题与示例代码内容之间插入**1**个空行。
- 单段描述跨行时需要使用悬挂式缩进。

## 2 完整docstring示例

```python
class Activation(nn.Layer):
    """
    The wrapper of activations.

    Args:
        act (str, optional): Activation name in lowercase. It must be one of {'elu', 'gelu',
            'hardshrink', 'tanh', 'hardtanh', 'prelu', 'relu', 'relu6', 'selu', 'leakyrelu', 'sigmoid',
            'softmax', 'softplus', 'softshrink', 'softsign', 'tanhshrink', 'logsigmoid', 'logsoftmax',
            'hsigmoid'}. Default: None, means identical transformation.

    Returns:
        A callable object of Activation.

    Raises:
        KeyError: When parameter `act` is not in the optional range.

    Examples:

        from paddleseg.models.common.activation import Activation

        relu = Activation("relu")
        print(relu)
        # <class 'paddle.nn.layer.activation.ReLU'>

        sigmoid = Activation("sigmoid")
        print(sigmoid)
        # <class 'paddle.nn.layer.activation.Sigmoid'>

        not_exit_one = Activation("not_exit_one")
        # KeyError: "not_exit_one does not exist in the current dict_keys(['elu', 'gelu', 'hardshrink',
        # 'tanh', 'hardtanh', 'prelu', 'relu', 'relu6', 'selu', 'leakyrelu', 'sigmoid', 'softmax',
        # 'softplus', 'softshrink', 'softsign', 'tanhshrink', 'logsigmoid', 'logsoftmax', 'hsigmoid'])"
    """
    ...
```