gpt4 book ai didi

python - 将新类生成到命名空间的装饰器

转载 作者:太空宇宙 更新时间:2023-11-03 13:28:38 24 4
gpt4 key购买 nike

我需要它的具体用例是弃用类名。

假设我们在早期版本中有类 A,我们想弃用它的名称但保持向后兼容性:

class A(B):
def __init__(self, *args, **kwargs):
warnings.warn('deprecation!')
super(A, self).__init__(*args, **kwargs)

... B 现在有了正确的实现。

当我们创建一个类 A 时,我们会在这里遇到弃用警告。我们还可以在 __init__ 上使用装饰器的 deprecated 模块。

不过,我想跳过这个过程,少写一些代码,希望能达到这样的效果:

@deprecated_alias('A')
class B:
# ... do something

我能否以某种方式将类名注入(inject)模块级命名空间,以便我可以像这样使用 A

最佳答案

Can I somehow inject the classname into the module-level namespace so that I can use A like this?

是的。类装饰器应该:

  • 使用 type 的 3 参数调用创建一个新类型,覆盖 __init__ 方法
  • 获取原始类的模块,sys.modules[original_class.__module__]
  • 使用 setattr 在模块命名空间中绑定(bind)新类
  • 返回原始类不变

例子:

import sys

def deprecated_alias(name):
def decorator(class_):
mod = sys.modules[class_.__module__]
if hasattr(mod, name):
raise Exception('uhoh, name collision')
NewClass = type(name, (class_,), {'__init__': ...})
setattr(mod, name, NewClass)
return class_
return decorator

@deprecated_alias('A')
class B:
pass

我不推荐这种方法 - 魔法太多了。它会混淆 IDE 并破坏自动完成功能。

也许是一种不那么神奇的方法?这也可以做成一个装饰器,如果你需要控制更精细的继承细节,可以使用 __subclasscheck__/__subclasshook__

class A(B):
def __init__(self, *args, **kwargs):
warnings.warn('deprecation!')
return B(*args, **kwargs)

关于python - 将新类生成到命名空间的装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51089327/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com