man*_*off 3 python numpy decorator python-decorators
我对python函数装饰器有一点了解.我认为我的问题的答案是否定的,但我想确定.有了装饰器和numpy数组,x = np.array([1,2,3])我可以覆盖x.sqrt()并改变行为.有什么方法可以np.sqrt(x)在Python中覆盖?
使用案例:处理数量包.希望能够在不改变当前使用的代码库的情况下获取不确定数量的平方根np.sqrt().
编辑:
我想np.sqrt在quantities包中修改以便以下代码可以工作(所有三个应该打印相同的结果,注意使用时的0不确定性np.sqrt()).我希望不要求最终用户修改他们的代码,但在quantities包中正确包装/装饰np.sqrt().目前有许多numpy函数被装饰(参见https://github.com/python-quantities/python-quantities/blob/ca87253a5529c0a6bee37a9f7d576f1b693c0ddd/quantities/quantity.py),但似乎只在x.func()调用时才起作用,而不是numpy.func(x).
import numpy as np
import quantities as pq
x = pq.UncertainQuantity(2, pq.m, 2)
print x.sqrt()
>>> 1.41421356237 m**0.5 +/- 0.707106781187 m**0.5 (1 sigma)
print x**0.5
>>> 1.41421356237 m**0.5 +/- 0.707106781187 m**0.5 (1 sigma)
print np.sqrt(x)
>>> 1.41421356237 m**0.5 +/- 0.0 dimensionless (1 sigma)
Run Code Online (Sandbox Code Playgroud)
如果我正确理解你的情况,你的用例实际上不是关于装饰(以标准方式修改你编写的函数)而是关于猴子修补: 修改其他人编写的函数而不实际更改该函数的定义的源代码.
你需要的成语就像是
import numpy as np # provide local access to the numpy module object
original_np_sqrt = np.sqrt
def my_improved_np_sqrt(x):
# do whatever you please, including:
# - contemplating the UncertainQuantity-ness of x and
# - calling original_np_sqrt as needed
np.sqrt = my_improved_np_sqrt
Run Code Online (Sandbox Code Playgroud)
当然,这只能改变未来的意义numpy.sqrt,而不是过去的意义.因此,如果有人numpy在上述之前进口并且已经numpy.sqrt以某种方式使用了你想要影响的东西,那么你就输了.(他们映射的名称numpy无关紧要.)
但是在上面的代码执行之后,numpy.sqrt所有模块的含义(无论是numpy在它之前还是在它之后导入)都将是my_improved_np_sqrt那些模块的创建者是否喜欢它(当然除非更多的monkeypatching numpy.sqrt
是在其他地方).
注意
这就是为什么猴子修补通常不被认为是好的设计风格.因此,如果您采取这种方式,请确保在所有相关文档中非常突出地宣布它.
哦,如果你不想修改其他代码而不是直接或间接从你自己的方法执行的代码,你可以引入一个装饰器,在调用之前执行monkeypatching并在调用后取消monkeypatching(重新分配original_np_sqrt)并应用该装饰器你所有的功能.确保你在那个装饰器中处理异常,这样就可以在所有情况下真正执行un-monkeypatching.