【发布时间】:2020-08-05 14:49:49
【问题描述】:
有时我想编写一个带有实例变量的类,它一方面应该在 __init__ 内部初始化,但另一方面也可以通过不同的函数(function_1 - function_3)从在某些事件发生后的内部或外部。
更新函数都依赖于相同的输入参数,但在初始化和以后的更新中工作相同。它们可能是类的成员(@staticmethod 或不是),也可能是从某个包导入的实用函数。
对于以后的更新,“元”更新函数(update_member_variables)显然应该是一个过程,i。 e.什么都不返回,只修改成员变量作为副作用。
但是,对于初始化,它最好是一个纯函数并返回变量的值,以便可以将它们分配给__init__ 中的变量。
这种冲突总是让我经历以下重复代码循环,__init__ 和 None-initializations 之外的声明,但永远不会导致令人满意的解决方案:
from some_utils import function_1, function_2, function_3
# A: duplicate code in update_member_variables
class Class:
def __init__(self, parameter):
self._variable_1 = function_1(parameter)
self._variable_2 = function_2(parameter)
self._variable_3 = function_3(parameter)
def update_member_variables(self, parameter):
self._variable_1 = function_1(parameter)
self._variable_2 = function_2(parameter)
self._variable_3 = function_3(parameter)
# B: instance variables declared outside __init__
class Class:
def __init__(self, parameter):
self.update_member_variables(parameter)
def update_member_variables(self, parameter):
self._variable_1 = function_1(parameter)
self._variable_2 = function_2(parameter)
self._variable_3 = function_3(parameter)
# C: boilerplate None-assignments
class Class:
def __init__(self, parameter):
self._variable_1 = None
self._variable_2 = None
self._variable_3 = None
self.update_member_variables(parameter)
def update_member_variables(self, parameter):
self._variable_1 = function_1(parameter)
self._variable_2 = function_2(parameter)
self._variable_3 = function_3(parameter)
# D: back to duplicated code in update_member_variables
class Class:
def __init__(self, parameter):
(
self._variable_1,
self._variable_2,
self._variable_3
) = self._derive_values(parameter)
def _derive_values(self, parameter):
return (
function_1(parameter),
function_2(parameter),
function_3(parameter),
)
def update_member_variables(self, parameter):
(
self._variable_1,
self._variable_2,
self._variable_3
) = self._derive_values(parameter)
选择 B 很诱人,但由于所有针对 __init__ 之外的成员变量声明的警告,我通常坚持使用 C 或 D,尽管它们看起来臃肿而笨重。
没有更好的方法来解决这种情况吗?也许在盒子外面?还是已经是 A-D 中最“优雅”或最干净的那个了?
相关问题:
在https://stackoverflow.com/a/51607441/3863847 中回答了类似的问题,但update_number 仅适用于初始化。接受的答案代码类似于我的 D,但没有 update_member_variables。
在https://stackoverflow.com/a/20661498/3863847 中回答了另一个相关问题。一般来说,Simeon Visser 指出,在初始化后确保对象一致是开发人员的责任,但无论如何,严格遵守该规则并不是必须的。我的情况是可以选B的情况吗? B的实例化对象至少是一致的。
【问题讨论】:
-
“所有警告”的原因是什么?我记得与此相关的事情与编写单元测试时的特定模拟有关。但是分配
Nonein__init__对规范没有帮助。在这种情况下,您可以基于实例而不是类来指定。 -
如果只是为了更好地阅读所涉及的类成员,C看起来还可以。
-
@progmatico:所有警告的原因似乎都是 PEP 8,尽管我还没有找到确切的段落。由于我也发现了另一个建议,如您所建议的 None-assignments,我将认为 C 是最好的版本。谢谢你。还要感谢您指导我使用 autospec。
标签: python oop initialization instance-variables