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

标签 python module

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

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()

DeprecationWarning: That has been deprecated, use the new features!

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

DeprecationWarning: that's deprecated!

float

但是,从包内(至少在顶层)这似乎是不可能的,因为我无法访问自己的模块。我将不得不创建另一个包来猴子修补主包。

有没有比子类化“模块”类和/或使用猴子修补另一个包的顶级模块的元包更好的方法来“弃用”从包访问变量?

最佳答案

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}")

这基本上是 PEP 中针对该问题略微改编的示例。

关于python - 子类化模块以弃用模块级变量/常量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45744919/

相关文章:

linux - 将模块.C添加到linux内核

python - 如何从 python 中的字符串中删除 ANSI 转义序列

python - celery 停止执行链

python - 从字符串中获取不在另一个列表中的单词列表

python - 如何在python程序中添加islice函数?

perl - 如何在 Unix 上通过命令行查找 Perl 模块版本号?

python - 使用 mechanize 检索 robots.txt 时出现 HTTP 403 错误

python - PyQt 和 py2exe : no sound from QSound after compiling to . exe

javascript - ES2015 模块初始化不起作用

Python type() 函数返回一个可调用对象