类顶层的类型提示的含义是什么?

问题描述 投票:0回答:1

我正在尝试理解 PyTorch 中名为

CrossEntropyLoss
的类的语法。我关心的部分是这样的:

class CrossEntropyLoss(_WeightedLoss):
    __constants__ = ['ignore_index', 'reduction', 'label_smoothing']
    ignore_index: int
    label_smoothing: float

    def __init__(self, weight: Optional[Tensor] = None, size_average=None, ignore_index: int = -100,
                 reduce=None, reduction: str = 'mean', label_smoothing: float = 0.0) -> None:
        super().__init__(weight, size_average, reduce, reduction)
        self.ignore_index = ignore_index
        self.label_smoothing = label_smoothing

[...]

我无法弄清楚第三行

ignore_index: int
和第四行
label_smoothing: float
的含义是什么。

它们看起来像

ignore_index
label_smoothing
的类型提示,但这些信息在
__init__
函数中似乎是多余的。

除此重复之外,以下类在两个地方使用不同的类型,并且不会在

mypy
中给出任何错误。

#!/usr/bin/env python3


class A:
    num: float

    def __init__(self, num: int = 5):
        self.num = num


a = A()
print("type(a.num) = " + str(type(a.num)))

# both lines give
## AttributeError: type object 'A' has no attribute 'num'
print("type(A.num) = " + str(type(A.num)))
print("A.num = " + str(A.num))

使用 Python 3.12 执行它会给出:

$ ./static_var_test.py 
type(a.num) = <class 'int'>    <--------------------- NOTE: not float
Traceback (most recent call last):
  File "./static_var_test.py", line 16, in <module>
    print("type(A.num) = " + str(type(A.num)))
                                      ^^^^^
AttributeError: type object 'A' has no attribute 'num'

mypy
的输出:

$ mypy --version
mypy 1.8.0 (compiled: yes)
$ mypy static_var_test.py 
Success: no issues found in 1 source file

类顶层的类型提示有何用处?

python type-hinting python-typing
1个回答
0
投票

不同情况的一些前奏:默认与未设置以及实例与类。

虽然没有必要定义类型提示注释,但可以区分这些用例,请参阅PEP 526

首先,您可以使用值显式声明变量(不一定需要类型提示。) 但是,存在一个问题,您是否希望整个 class 的属性在所有实例之间共享 (

ClassName.shared
),还是希望为每个 instance (
Apple("Big").price
) 提供默认值。

官方的例子是一艘船,同级别的每艘船应该有相同的属性。 然而,每个实例都可以有自己的队长,但您想要声明一个默认值并且可能更改/访问它,从函数访问默认参数不是很干净。 由于实例默认值和类默认值是共享的,因此有

ClassVar
类型提示来区分这些情况。

class BasicStarship:
    captain: str = 'AI'               # instance variable with default
    damage: int                           # instance variable without default
    stats: ClassVar[Dict[str, int]] = {}  # class variable


  def __init__(self, damage: int, captain: str = None):
        self.damage = damage
        if captain:
            self.captain = captain  # Else keep the default

类顶层的类型提示有何用处?

  • 一个论点是您可以更轻松地跟踪要实现的默认实例值。 如果您有一些带有自定义 init 函数的继承层次结构,您可能无法 100% 确定所有类是否都实现所有默认值。 这使得它更类似于 C 或 Java,您也可以在其中了解此概述; TL;DR 和我认为更干净的编程

  • 它们与 init 的参数并不多余。 后者可能更全面,例如如果允许多种类型,并且在最终值之前进行一些预处理

class Coin:
    values : List[int]

    def __init__(self, values : Union[List[int], int]):
        # fix single values entries
        if not isisntance(Iterable, values):
           self.values = [values] # correct type from 2 allowed.

此外,注释与数据类

完美结合
© www.soinside.com 2019 - 2024. All rights reserved.