python - 类设计: Initializing and updating instance variables elegantly

标签 python oop initialization instance-variables

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

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

对于以后的更新,“元”更新函数(update_member_variables)显然应该是一个过程,即。 e.不返回任何内容,仅修改成员变量作为副作用。 但是,对于初始化,它最好是一个纯函数并返回变量的值,以便可以将它们分配给 __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)


# 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 的实例化对象至少是一致的。

最佳答案

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

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

关于python - 类设计: Initializing and updating instance variables elegantly,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61367565/

相关文章:

python - 如何将参数传递给 __init__ 函数

python - pandas shift 将我的列从整数转换为 float 。

java - 使用 JdbcTemplate 字段扩展 java spring 单例抽象类

c++ - 在 Tic Tac Toe 中为领带游戏创建函数

c++ - 静态变量阴影全局

java - 内存中的 "null"在哪里

python - 将多个字典以长格式合并到一个 pandas 数据框中

python - socket.io客户端和tornado python服务器之间的Websocket连接

java - android 中很难面向对象 "transplantation"

c - 为 C 结构体数组中的每个元素分配默认值