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

有时我想编写一个带有实例变量的类,它一方面应该在内部初始化__init__,但另一方面也可以在某些事件发生后从内部或从外部通过不同的函数 ( function_1- ) 进行更新。function_3


更新函数都依赖于相同的输入参数,但在初始化和以后的更新中工作相同。它们可能是类的成员(@staticmethod或不是),也可能是从某个包导入的实用函数。


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


这种冲突总是让我经历以下重复代码、外部声明__init__和None初始化的循环,但从未导致令人满意的解决方案:


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)

选择 B 很诱人,但由于对 之外的成员变量声明的所有警告__init__,我通常坚持使用 C 或 D,尽管它们看起来臃肿而笨重。


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


相关问题:


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


在https://stackoverflow.com/a/20661498/3863847中回答了另一个相关问题。一般来说,Simeon Visser 指出,在初始化后确保对象一致是开发人员的责任,但无论如何,严格遵守该规则并不是必须的。我的情况是可以选B的情况吗?B 的实例化对象至少是一致的。


慕沐林林
浏览 104回答 2
2回答

德玛西亚99

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我觉得使用属性可以更好地更新变量。

ITMISS

在https://stackoverflow.com/a/19292653/3863847中,sthenault 给出了可读性作为不应在外部声明实例变量的原因__init__。据我所知,这植根于 PEP 8,这就是 pylint 抱怨违规行为的原因——我从不选择 B。sthenault 还建议在 中进行无分配__init__,就像 progmatico 在我的问题下方的评论中所做的那样,这对应于我的版本 C。尽管我希望有一个优雅的技巧以某种方式规避这种情况,但我暂时将 C 视为“最 Pythonic”。如果以后有人想出我正在寻找的这种神奇的解决方案,我将切换接受的答案。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python