为什么在 Python class 中使用 self.foo = self.foo in __init__?

why the use of self.foo = self.foo in __init__ in Python class?

我多次看到人们在他们的 init 函数中写了以下内容。

def __init__(self,**attr):
 self.foo = self.foo


这是一个(有用的)技巧吗? 有人可以向我解释吗?谢谢。

已更新。

例如,在graph.py中(用于定义图class)在networkx中 我看到以下内容。

def __init__(self, incoming_graph_data=None, **attr):
 self.graph_attr_dict_factory = self.graph_attr_dict_factory
 self.node_dict_factory = self.node_dict_factory
 

使用更多的代码,它的使用在两种不同的情况下可能有一定的意义,尽管它仍然不总是实现它所达到的目标的最佳方式:

class MyClass:
    baz = 1

    def __init__(self):
        self.baz = self.baz
        self._foo = None
        self.bar = None
        self.foo = self.foo

    @property
    def foo(self):
        if self._foo is None:
            self._foo = 1
        return self._foo

    @foo.setter
    def foo(self, value):
        self.bar = 0
        self._foo = value


m1 = MyClass()
m2 = MyClass()
print(m1.foo, m1.bar, m1.baz)
m1.baz = 2
MyClass.baz = 3
print(m1.baz, m2.baz, MyClass.baz)

有点做作,但是 self.foo = self.foo 会实现的是 .foo 属性 的 getter 和 setter 都会被调用。

人们说 .foo 无法在此时访问并且会提出 AttributeError 在您分享的有限情况下是正确的,但当然定义 属性 可以做到也可在构造函数中使用,如示例所示。我通过先定义 ._foo 来使代码更清晰一些,但是当然您可以先在 setter 中定义它,但不推荐这样做。

setters 和 getters 是 运行 主要是因为它们有副作用,这是使用属性的一个原因(另一个常见的原因是你想限制访问,或限制可能的值)。

编辑:networkx 中的示例正在将 class 属性重新分配给实例属性(在我尝试之前我不知道它有效)。在我的示例中查看最终 print() 的结果:

m1.baz = 2
MyClass.baz = 3
print(m1.baz, m2.baz, MyClass.baz)

结果:

2 1 3

networkx 这样做的原因可能是允许您提供不同的 Graph 工厂方法,而不影响 class - 如果您分配给它,只有您的实例会得到一个新的graph_attr_dict_factory,但它是用 class 工厂方法初始化的。

但是,请注意,即使 networkx 没有像在构造函数中那样设置它,用户仍然可以稍后为实例分配一个新工厂并看到相同的行为 - 唯一真正的区别是该实例到那时不会有实例属性,而是会访问 class 属性。其他代码可能依赖于这种区别,因此删除赋值 可能会 对其他地方产生影响,但它对 class 本身的直接功能没有任何作用。