【问题标题】:Resetting/reloading class attributes of nested class at runtime在运行时重置/重新加载嵌套类的类属性
【发布时间】:2019-03-15 13:14:42
【问题描述】:

我在 Python 3 中使用嵌套类来“记账”。类结构(高度简化)如下所示:

class BookKeeping:

    class ItemA:
        count = 0
        item_list = []

        @classmethod
        def add(cls, item_a):
            cls.count += 1
            cls.item_list.append(item_a)

    class ItemB:
        count = 0
        item_dict = {}

        ...

这个类可以方便地跟踪和访问我正在建模的系统的一些“全局”属性。拥有嵌套类允许清晰的命名空间。例如,在任何模块中我都可以... import BookKeeping as BK 并检查有多少ItemB 对象(BK.ItemB.count)。

在我的程序中的某个时刻,我想“重置”所有类属性,即我想再次将 BookKeeping.ItemA.count 设置为 0 并清空列表和字典等。

显然,我可以添加一个顶级类方法,例如 BookKeeping.reset(),它会“手动”重置所有值,例如:

class BookKeeping:

    @classmethod
    def reset(cls):
        cls.ItemA.count = 0
        cls.ItemA.item_list = []
        cls.ItemB.count = 0

        ...

但是,这对我来说似乎是一种容易出错的方法,它涉及到这个类的“维护”(我可能忘记重置一些属性)。请注意,我的真实课程比我提供的示例更复杂。

在运行时将所有类属性重置为其原始状态的最简单方法是什么?

【问题讨论】:

  • 你能不能有一个单独的类(例如BookKeepingSession 或其他东西)将这些值保存为 instance 属性而不是 class 属性?然后你可以在每次你想做一些不相关的BookKeeping时创建一个新的BookKeepingSession

标签: python python-3.x class oop nested


【解决方案1】:

所以提前:你真的应该这样做吗?应该不会吧。

实际上,我建议您尝试重新考虑您的项目结构,因为通常应该避免全局状态。

如果你仍然想这样做......

当心,前面有一些未经测试的(!)奥术魔法:

import copy

class BookKeeping(object):
    __backup = {}

    class ItemA(object):
        ...

    class ItemB(object):
        ...

    @classmethod
    def reset(cls):
        for name, backup in cls.__backup.items():
            inner_cls = getattr(cls, name)
            for k, v in backup.items():
                setattr(inner_cls, k, copy.deepcopy(v))

for i in dir(BookKeeping):
    if not i.startswith("_"):
        obj = getattr(BookKeeping, i)
        BookKeeping.__backup[i] = {k: copy.deepcopy(getattr(obj, k)) for k in dir(obj)}

附加说明:这通常是一个棘手的问题。但是您也可以对其他嵌套结构使用相同的技术,并以不同的方式处理类型,而不是以不同的方式处理第一级。

这是一个问题,因为您不想 deepcopy 类型本身,因为这会在当时所有活动对象以及所有新对象以及当前新的全局状态中复制状态。

【讨论】:

  • 是的,我已经意识到我最初认为是一个干净方便的解决方案,但结果却存在一些缺陷。我已经重构了我的代码,这样我就不必再处理任何全局状态了。我想,Python 让它“看起来很丑”和不方便的事实也应该强烈表明某些东西不是很好。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 2019-09-24
  • 2013-09-20
相关资源
最近更新 更多