类设计:优雅地初始化和更新实例变量

时间:2020-04-22 14:24:58

标签: python oop initialization instance-variables

有时我想编写一个带有实例变量的类,这些实例变量一方面应在__init__内部初始化,但另一方面也可以稍后通过不同的函数(function_1-{{1 }})发生事件后从内部还是外部。

更新功能全部取决于相同的输入参数,但在初始化和稍后更新中的工作方式相同。它们可能是类的成员(是否为function_3)或从某些程序包导入的实用程序函数。

对于以后的更新,“元”更新功能(@staticmethod)显然应该是一个过程,即: e。什么也不返回,仅修改成员变量作为副作用。 但是,对于初始化,它最好是一个纯函数并返回变量的值,以便可以将它们分配给update_member_variables内部的变量。

这种冲突总是使我经历以下重复代码的循环,__init____init__初始化之外的声明,但是从没有找到令人满意的解决方案:

None

选择B是很诱人的方法,但是由于针对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) 之外的成员变量声明提出了所有警告,因此我通常坚持使用C或D,尽管它们看起来过大且笨重。

有没有更好的方法来解决这种情况?也许在盒子外面?还是A-D中最“优雅”或干净的一个?

相关问题:

https://stackoverflow.com/a/51607441/3863847中回答了类似的问题,但是__init__仅适用于初始化。接受的答案的代码类似于我的D,但没有update_number

https://stackoverflow.com/a/20661498/3863847中回答了另一个相关问题。通常,Simeon Visser指出,确保初始化后的对象一致是开发人员的责任,而且无论如何都不必严格遵循此规则。我的案子可以选择B吗? B的实例化对象至少是一致的。

2 个答案:

答案 0 :(得分:1)

class A:
    def __init__(self, parameter):
        self._variable_1 = function_1(parameter)
        self._variable_2 = function_2(parameter)
        self._variable_3 = function_3(parameter)

    @property
    def variable_1(self):
        return self._variable_1

    @variable_1.setter
    def variable_1(self, value):
        self._variable_1 = function_1(value)

    ... so on and so forth for other variables ...

 a = A(parameter1)
 # update based on parameters
 a.variable_1 = parameter2

我觉得使用属性可以更好地更新变量。

答案 1 :(得分:0)

https://stackoverflow.com/a/19292653/3863847中,sthenault提供了可读性,这是为什么不应在__init__之外声明实例变量的原因。

据我所知,这植根于PEP 8,这就是为什么pylint抱怨违规-我从不选择B。

sthenault还在__init__中建议“无分配”,就像progmatico在我的问题下方的注释中所做的一样,该注释与我的C版本相对应。

尽管我希望有一个巧妙的技巧来以某种方式规避这种情况,但我暂时将C视为“最pythonic”。如果以后有人提出我正在寻找的这种神奇的解决方案,我将切换接受的答案。