我多次看到人们在他们的 init 函数中编写以下内容。
def __init__(self,**attr):
self.foo = self.foo
这是一个(有用的)技巧吗? 有人可以向我解释一下吗?谢谢。
已更新。
例如,在networkx中的graph.py(用于定义Graph类)中 我看到以下内容。
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 中定义它,但不建议这样做。
如果 setter 和 getter 有副作用,那么它们的运行就非常重要,这是使用属性的原因之一(另一个常见原因是您想要限制访问或限制可能的值)。
编辑:networkx
中的示例是将类属性重新分配给实例属性(在尝试之前我不知道它有效)。请参阅我的示例中最终 print()
的结果:
m1.baz = 2
MyClass.baz = 3
print(m1.baz, m2.baz, MyClass.baz)
结果:
2 1 3
networkx 这样做的原因可能是允许您提供不同的图形工厂方法,而不影响类 - 只有当您分配给它的 时,您的实例才会获得一个新的方法graph_attr_dict_factory
,但它是使用类工厂方法初始化的。
但是,请注意,即使 networkx
没有像构造函数中那样进行设置,用户仍然可以稍后为实例分配一个新工厂并看到相同的行为 - 唯一真正的行为不同之处在于,到目前为止,实例不具有实例属性,而是会访问类属性。其他代码可能依赖于这种区别,因此删除赋值可能会对其他地方产生影响,但它对于类本身的直接功能没有任何作用。
关于python - 为什么在Python类的__init__中使用self.foo = self.foo?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71551468/