代码之家  ›  专栏  ›  技术社区  ›  MSeifert

将模块子类化以弃用模块级变量/常量?

  •  4
  • MSeifert  · 技术社区  · 7 年前

    假设我有一个模块,我想反对该模块中的某些内容。这对于函数来说非常容易,基本上可以使用装饰器来完成:

    import warnings
    
    def deprecated(func):
        def old(*args, **kwargs):
            warnings.warn("That has been deprecated, use the new features!", DeprecationWarning)
            return func(*args, **kwargs)
        return old
    
    @deprecated
    def func():
        return 10
    
    func()
    

    10

    __getattribute__ 发出警告:

    我在这里使用NumPy只是为了说明原理:

    import numpy as np
    
    class MyMod(type(np)):   # I could also subclass "types.ModuleType" instead ...
        def __getattribute__(self, name):
            if name in {'float', 'int', 'bool', 'complex'}:
                warnings.warn("that's deprecated!", DeprecationWarning)
            return object.__getattribute__(self, name)
    
    np.__class__ = MyMod
    
    np.float
    

    浮动

    然而,这似乎不可能从包内实现(至少在顶层),因为我无法访问自己的模块。我必须创建另一个包,让monkey修补主包。

    1 回复  |  直到 7 年前
        1
  •  2
  •   MSeifert    6 年前

    PEP 562 已被接受并将添加到Python 3.7中(在编写本文时未发布),这将允许(或至少大大简化)弃用模块级常量。

    __getattr__ 模块中的函数。例如,在这种情况下:

    import builtins
    import warnings
    
    def __getattr__(name):
        if name == 'float':
            warnings.warn("That has been deprecated, use the new features!", DeprecationWarning)
            return builtins.float
        raise AttributeError(f"module {__name__} has no attribute {name}")
    

    这基本上是政治公众人物中的示例,稍微适合这个问题。