为什么在 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 本身的直接功能没有任何作用。
我多次看到人们在他们的 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 本身的直接功能没有任何作用。