为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕沐林林 2022-10-18 17:07:52
有时我想编写一个带有实例变量的类,它一方面应该在内部初始化__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_variablesclass 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-assignmentsclass 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 的实例化对象至少是一致的。
查看完整描述

2 回答

?
德玛西亚99

TA贡献1770条经验 获得超3个赞

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

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


查看完整回答
反对 回复 2022-10-18
?
ITMISS

TA贡献1871条经验 获得超8个赞

https://stackoverflow.com/a/19292653/3863847中,sthenault 给出了可读性作为不应在外部声明实例变量的原因__init__

据我所知,这植根于 PEP 8,这就是 pylint 抱怨违规行为的原因——我从不选择 B。

sthenault 还建议在 中进行无分配__init__,就像 progmatico 在我的问题下方的评论中所做的那样,这对应于我的版本 C。

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


查看完整回答
反对 回复 2022-10-18
  • 2 回答
  • 0 关注
  • 101 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信