Jos*_*vin 10 python hook global decorator deprecated
我已经看到装饰器允许你标记一个不推荐使用的函数,以便在使用该函数时给出警告.我想对全局变量做同样的事情,但我想不出一种检测全局变量访问的方法.我知道globals()函数,我可以检查它的内容,但这只会告诉我是否定义了全局(如果该函数被弃用并且不是全部删除它仍将是它),如果它实际上被使用的话.我能想到的最佳选择是这样的:
# myglobal = 3
myglobal = DEPRECATED(3)
Run Code Online (Sandbox Code Playgroud)
但除了如何让DEPRECATED行为与'3'完全相同的问题之外,我不确定DEPRECATED可以做什么,这样可以让你每次访问时都能检测到.我认为它能做的最好就是遍历所有全局的方法(因为Python中的所有东西都是一个对象,所以即使'3'也有方法,转换为字符串之类的东西)和'装饰'它们都被弃用了.但那并不理想.
有任何想法吗?还有其他人解决过这个问题吗?
Bri*_*ian 13
你不能直接这样做,因为没有办法拦截模块访问.但是,您可以使用您选择的充当代理的对象替换该模块,以查找对某些属性的访问:
import sys, warnings
def WrapMod(mod, deprecated):
"""Return a wrapped object that warns about deprecated accesses"""
deprecated = set(deprecated)
class Wrapper(object):
def __getattr__(self, attr):
if attr in deprecated:
warnings.warn("Property %s is deprecated" % attr)
return getattr(mod, attr)
def __setattr__(self, attr, value):
if attr in deprecated:
warnings.warn("Property %s is deprecated" % attr)
return setattr(mod, attr, value)
return Wrapper()
oldVal = 6*9
newVal = 42
sys.modules[__name__] = WrapMod(sys.modules[__name__],
deprecated = ['oldVal'])
Run Code Online (Sandbox Code Playgroud)
现在,您可以将其用作:
>>> import mod1
>>> mod1.newVal
42
>>> mod1.oldVal
mod1.py:11: UserWarning: Property oldVal is deprecated
warnings.warn("Property %s is deprecated" % attr)
54
Run Code Online (Sandbox Code Playgroud)
缺点是您在访问模块时正在执行两次查找,因此会有轻微的性能损失.
看吧:
from types import *
def wrapper(f, warning):
def new(*args, **kwargs):
if not args[0].warned:
print "Deprecated Warning: %s" % warning
args[0].warned = True
return f(*args, **kwargs)
return new
class Deprecated(object):
def __new__(self, o, warning):
print "Creating Deprecated Object"
class temp(o.__class__): pass
temp.__name__ = "Deprecated_%s" % o.__class__.__name__
output = temp.__new__(temp, o)
output.warned = True
wrappable_types = (type(int.__add__), type(zip), FunctionType)
unwrappable_names = ("__str__", "__unicode__", "__repr__", "__getattribute__", "__setattr__")
for method_name in dir(temp):
if not type(getattr(temp, method_name)) in wrappable_types: continue
if method_name in unwrappable_names: continue
setattr(temp, method_name, wrapper(getattr(temp, method_name), warning))
output.warned = False
return output
Run Code Online (Sandbox Code Playgroud)
>>> a=Deprecated(1, "Don't use 1")
Creating Deprecated Object
>>> a+9
Deprecated Warning: Don't use 1
10
>>> a*4
4
>>> 2*a
2
Run Code Online (Sandbox Code Playgroud)
这显然可以改进,但要点就在那里.
| 归档时间: |
|
| 查看次数: |
5012 次 |
| 最近记录: |