【问题标题】:Deprecate class to dictionary properties python弃用类到字典属性python
【发布时间】:2020-05-06 17:01:51
【问题描述】:

在 python 中,我有一个类,其中一个属性是保存数据的其他类,如下所示:

class A:
    class Params:
        def __init__(self):
            self.param1 = None
            self.param2 = None
            ...

    def __init__(self):
        self.parameters = self.Params()

这样,如果有人想更改self.parameters 中的参数之一,他可以写self.parameters.param1 = ...

我想将保存参数的类 Params 更改为字典

class A:
    def __init__(self):
        self.parameters = {
            'self.param1': None
            'self.param2': None
        }

这样,如果有人想更改任何内容,他可以改为写self.parameters['param1'] = ...。我已经实现了这个更改(在开发分支中)并且它有效。问题是其他人使用该代码,如果我进行此更改,它将破坏他们的代码(这是简单的修复,但仍然如此)。

我想知道是否有任何方法可以做到,这样如果有人以旧方式(即parameters.param1 = ...)写作,它仍然可以工作,但当他这样做时会打印DEPRECATED 消息,这样我可以制作一个过渡窗口,让人们从旧方式到新方式。我想出的唯一方法是如果我更改属性的名称,我可以保留旧代码并添加log.warning,但我不想更改属性的名称,所以如果有人能想到办法这样做会很棒:)

【问题讨论】:

    标签: python dictionary oop deprecated


    【解决方案1】:

    您可以定义使Params 实现映射协议,然后在属性访问时产生弃用警告。

    class Params:
        def __init__(self):
            ...  # As before
    
        def __setitem__(self, key, value):
            # This check is optional, to prevent creating new attributes
            if not hasattr(self, key):
                raise ValueError(f"No such parameter {key}")
            setattr(self, key, value)
    
        __getitem__ = getattr
    
        def __setattr__(self, attr, value):
            warnings.warn("Don't set attributes directly", DeprecationWarning)
            super().__setattr__(attr, value)
    
        def __getattribute__(self, attr):
            warnings.warn("Don't access attributes directly", DeprecationWarning)
            super().__getattribute__(self, attr)
    

    现在您的下一个版本将支持这两种技术,但属性访问会引发警告。在之后的版本中,你可以去掉Params类。

    class A:
        def __init__(self):
            self.parameters = {
                'param1': None
                'param2': None
            }
    

    【讨论】:

    • 感谢您的快速回复!实际上,我刚刚意识到了一种类似的方法(虽然你的更好?),其中类继承自dict,我使用super 来初始化类。
    • 我还有一个问题(我可以绕过但用一种不优雅的方式)。 hasstr 调用 __getattribute__ (我学到了艰难的方法:)所以每当我正确设置属性(即param['key'] = value)时,我都会收到不直接访问属性的警告。因为我知道所有属性,所以我可以不用hasstr,但我想知道您是否有解决方案。谢谢!又来了!
    • 我没有按我应该的那样修改这个问题。在我预期覆盖__getattribute__ 以提供弃用之前,我使用了hasattr,事后看来我不应该覆盖__getattribute__。唯一想到的是定义一个描述符,其__get____set__ 方法提供弃用警告,而不是覆盖__setattr____getattribute__
    • 我设法让它工作,我确实需要在几个地方修改你的代码。我仍然很高兴,因为我了解了这些神奇的功能:)
    • 随时更新此答案(甚至发布您自己的单独答案);我对DeprecationWarning 的来源做了一个小修复,但这完全未经测试。
    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    • 2019-01-13
    相关资源
    最近更新 更多