python 类变量在 __init__ 中更改时可以成为实例变量吗?

2023-12-23

据我所理解var is a 类变量 here:

class MyClass:
    var = 'hello'

    def __init__(self):
        print(self.var)

那是一个实例变量:

class MyClass:

    def __init__(self, var):
        self.var = var
        print(self.var)

我遇到了一个问题,我正在寻找一种方法来使类型提示成为可能实例变量。我当然可以输入参数def __init__(self, var: str):但这不会影响实例变量 itself.

然后我注意到一些描述(比如here https://stackoverflow.com/questions/44959876/type-hints-convention-for-instance-variables-python)他们使用了这个词实例变量 for a var像这样:

class MyClass:
    var : str = 'hello'

    def __init__(self, var : str = None):
        self.var = var if var
        print(self.var)

这确实是解决方案,但这仍然是一个解决方案吗?实例变量?因为它是在类主体中定义的,所以它将是类变量以我的理解。如果您使用 var 列表,则对此 list-var 的所有更改都将在实例上共享。

但在这种情况下不会有问题,因为字符串被替换并且不会被其他实例共享。然而,如果你称它为实例变量我不知道是否应该像这样使用它来让类型提示起作用。


这确实是解决方案,但这仍然是一个实例变量吗?因为它是在类主体中定义的,所以在我的理解中它将是一个类变量。 [...snip...] 但是,如果您将其称为实例变量,那么对我来说似乎是错误的,并且我不知道是否应该像这样使用它只是为了让类型提示起作用。

无论如何,我也有同样的不适。看起来我们在概念上混合了两个概念,只是为了拥有更清晰的类型注释。

然而,我已经问过 Guido 一两次这个问题,看来他确实更喜欢将这些类属性视为实例属性。

无论如何,为了回答您的核心问题,如果我们这样做:

class Test:
    field1: int
    field2: str = 'foo'

Then...

  1. PEP 484 and 526 compliant type checkers will treat this class as if:
    1. 它有一个名为的实例属性field1
    2. 它有一个名为的实例属性field2其默认值为“foo”(根据PEP 526 https://www.python.org/dev/peps/pep-0526/#class-and-instance-variable-annotations).
  2. At runtime, ignoring type hints, Python will:
    1. 添加班级注解 named field1来测试,但是not一类属性。 (类注释不会自动转换为类属性。)
    2. 添加两个类注解 named field2测试以及课程属性 named field2包含值“foo”。

所以,它可能会变得有点混乱。

但无论如何,这引出了一个问题:我们如何向类型检查器表明我们希望某个字段真正成为类属性?

嗯,事实证明 PEP 484 最近进行了修订以包含ClassVar类型注释 http://mypy.readthedocs.io/en/latest/python36.html#syntax-for-variable-annotations-pep-526,它正是这样做的。

因此,如果我们想添加一个新的类属性,我们可以这样做:

from typing import ClassVar

class Test:
    field1: int
    field2: str = 'foo'
    field3: ClassVar[int] = 3

So now, field3应被视为默认值为“3”的类属性。

(注:ClassVar 已添加到typing对于 Python 3.5.3——如果您使用的是旧版本typing与 Python 3.5 捆绑在一起,您可以通过安装来获得该类型的“向后移植”typing_extensions通过 pip 和导入的第三部分模块ClassVar从那里开始。)

我认为您是否决定采用这种方法或不使用它是个人喜好。

一方面,Guido 的观点,几乎从定义上来说,定义了什么是“Pythonic”或不是“Pythonic”,所以从这个立场来看,采用这种新的习惯用法是没有问题的。此外,语言本身正在缓慢但肯定地转变以采用这种新的习语——请参阅最近接受的PEP 557 https://www.python.org/dev/peps/pep-0557/例如,最终遵循将类属性/类注释视为实例属性的相同习惯用法。

另一方面,人们很难摆脱这种挥之不去的担忧,即这种微妙的差异会导致未来的问题。在这种情况下,您可以坚持使用标准方法,将所有字段设置在其中__init__。这种方法还具有保持代码与 Python 2 和 3.x - 3.5 兼容的好处。

中间立场可能就是根本不使用类属性,以任何方式、形状或形式,并且坚持使用类注释。这有点限制,因为我们不能再给实例变量默认值,但我们现在可以完全避免将类属性与实例属性混为一谈。 (如前所述,并如评论中指出的那样,类注释没有添加为类属性.)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python 类变量在 __init__ 中更改时可以成为实例变量吗? 的相关文章

随机推荐