gpt4 book ai didi

python - 如何使用装饰器将参数绑定(bind)到静态方法函数?

转载 作者:太空宇宙 更新时间:2023-11-03 17:19:57 25 4
gpt4 key购买 nike

我的问题如下所示:

class foo(obj):

def __init__(self, st='123'):
self.st = st

def process(self, x):
self.st += x

@staticmethod
def do_foo(x, myfoo=None):
if myfoo is None:
myfoo = foo()
myfoo.process(x)

def wrapper(fn, st):

foo_func = foo(st)
foo.do_foo = functools.partial(foo.do_foo, myfoo=foo_func)
fn()
print foo_func.st

return wrap

@wrapper('stst')
def pro():
foo.do_foo('double')

def pro2():
foo.do_foo('double')

pro2() # <--- normal foo.do_foo
pro() # <--- partialed foo.do_foo
pro2() # <--- partialed foo.do_foo

我想创建 wrapper 装饰器来包装静态方法 foo.do_foo 与自定义 foo 类,并在 pro( ) 执行后,这个装饰器能够跨 foo 对象做一些工作。即保存变量值。

在上面的代码中,包装器如何在全局范围内永远更改 foo.do_foo ,而不仅仅是在装饰器范围内更改它。

那么如何让 foo.do_foo 仅在装饰器范围内更改而不是全局更改?

最佳答案

这是基于 gist.github.com code 的略有不同的答案链接到您的评论(这似乎是基于我的答案的第一个版本)。

正如我最初所说,在我看来,您需要做的就是使 wrapper() 成为一个装饰器工厂函数,而不是装饰器本身 - 换句话说使其成为一个根据其参数创建并返回装饰器的函数。

正如我在回复您的评论时提到的,问题在于 Prof.do staticmethod 本质上是一个全局变量,如果包装的函数更改了它,这将影响对其的所有后续调用 -这是您问题的根本原因。

解决方法是让装饰器创建的 wrapped() 函数在调用装饰函数之前保存 Prof.do 的值,然后再恢复它,这样这些更改仅影响对通过它进行的函数的调用。这可以防止它对 Prof.do 所做的事情弄乱可能创建的其他包装函数中对其的其他调用。它还可以防止其效果累积。

我通过将静态方法的更改和恢复封装在 contextmanager 中。辅助功能。需要这样做的一个缺点是它增加了调用包装函数所涉及的开销。

import contextlib
import functools

class Prof(object):
def __init__(self, p='s'):
self.p = p

@staticmethod
def do(x, obj=None):
if obj is None:
obj = Prof()
obj.dprint(x)
print

def dprint(self, x):
print self.p, x
self.p += x

def wrapper(st):
@contextlib.contextmanager
def prof_context(obj): # could also be defined outside of wrapper function
# save current staticmethod and replace it with partial below
saved_method, Prof.do = Prof.do, functools.partial(Prof.do, obj=obj)
yield
# undo staticmethod modification
Prof.do = staticmethod(saved_method)

def decorator(fn):
@functools.wraps(fn)
def wrapped():
obj = Prof(st)
print 'current: obj.p is %r' % obj.p
with prof_context(obj):
fn()

return wrapped

return decorator

def do_p():
Prof.do('do')

@wrapper('do_p2')
def do_p2():
Prof.do('do2')

print '#A do_p():'
do_p()
print '#B do_p2():'
do_p2()
print '#C do_p():'
do_p()
print '#D do_p2():'
do_p2()
print '#E do_p():'
do_p()
print '#F do_p():'
do_p()

输出:

#A do_p():
s do

#B do_p2():
current: obj.p is 'do_p2'
do_p2 do2

#C do_p():
s do

#D do_p2():
current: obj.p is 'do_p2'
do_p2 do2

#E do_p():
s do

#F do_p():
s do

关于python - 如何使用装饰器将参数绑定(bind)到静态方法函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33271062/

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