在 ctor 中编写数据成员是否更像 pythonic?

Is writing data members inside ctor more pythonic?

我在python的有限经验表明

class Person:
    def __init__(self):
        self.data: Tuple[int, str] = (5, "M")
        print("DONE")

更常见
class Person:
    data: Tuple[int, str] = (5, "M")
    def __init__(self):
        print("DONE")

有什么理由支持第一个版本吗?

这是创建不同的属性,第一个是 instance 属性(对象的每个实例都是唯一的),第二个是 class 属性,在这个 class 的对象之间共享。

这是一个快速演示(我将属性更改为可变对象):

from typing import List, Union

class PersonA:
    def __init__(self):
        self.data: List[Union[int, str]] = [5, "M"]
        print("DONE")
        
class PersonB:
    data: List[Union[int, str]] = [5, "M"]
    def __init__(self):
        print("DONE")

pa1 = PersonA()
pa2 = PersonA()
pb1 = PersonB()
pb2 = PersonB()

现在让我们改变一个对象并查看另一个对象:

>>> pa1.data[0] = 1
>>> pa2.data
[5, 'M']  # unchanged, as instance attribute

>>> pb1.data[0] = 1
>>> pb2.data
[1, 'M']  # changed as affects all objects of the class