刷新d

2024-10-05 13:01:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图编写一个decorator,它在被调用后“刷新”,但是刷新只在最后一个函数退出后发生一次。下面是一个例子:

@auto_refresh
def a():
    print "In a"

@auto_refresh
def b():
    print "In b"
    a()

如果调用了a(),我希望在退出a()之后运行刷新函数。如果调用b(),我希望在退出b()之后运行刷新函数,而不是在由b()调用时在a()之后运行。下面是一个类执行此操作的示例:

^{pr2}$

如果我跑的话

b()
print '---'
b(refresh=True)
print '---'
b(refresh=False)

我得到以下输出:

Initializing decorator
Initializing decorator
Before function
In b
Before function
In a
After function
After function
---
Before function
In b
Before function
In a
After function
After function
Refreshing
---
Before function
In b
Before function
In a
After function
After function

因此,当以这种方式编写时,不指定refresh参数意味着刷新默认为False。有人能想出一种方法来改变它,使refresh在未指定时是True?改变

refresh = False

refresh = True

装潢师不工作:

Initializing decorator
Initializing decorator
Before function
In b
Before function
In a
After function
Refreshing
After function
Refreshing
---
Before function
In b
Before function
In a
After function
Refreshing
After function
Refreshing
---
Before function
In b
Before function
In a
After function
Refreshing
After function

因为refresh在第一种和第二种情况下被调用多次,在最后一种情况下调用一次(在第一种和第二种情况下应该是一次,而不是在最后一种情况下)。在


Tags: 函数infalsetrueautodef情况function
3条回答

以线程安全的方式计算“嵌套”的数量是使用thread-local storage的一个很好的例子:

import threading
mydata = threading.local()
mydata.nesting = 0

class auto_refresh(object):

  def __init__(self, f):
    self.f = f

  def __call__(self, *args, **kwargs):
    mydata.nesting += 1
    try: return self.f(*args, **kwargs)
    finally:
      mydata.nesting -= 1
      if mydata.nesting == 0:
        print 'refreshing'

如果您不关心线程,只要您的Python安装是在启用线程的情况下编译的(而现在几乎所有这些都启用了),这仍然可以正常工作。如果您担心没有线程的特殊Python安装,请将import语句改为

^{pr2}$

大致如the docs中建议的那样(除了文档对导入结果使用了一个特殊的“private”名称,而且没有真正的原因,所以我使用了一个简单的名称;-)。在

我认为维护一个“嵌套刷新计数”可能更简单,该计数在每次刷新修饰调用之前递增,在每次刷新修饰调用之后递减(在finally块中,这样计数就不会弄乱);每当计数为零时运行刷新例程。在

我不清楚你到底想用这个设计做什么,因此,这是不是个好主意。考虑一下这是否是正确的方法。在

不过,我认为这符合你的要求。一个公共对象(在本例中命名为auto_refresh)由所有的“decorated”方法共享,并且该对象保留一个关于调用堆栈深度的计数器。在

这不是线程安全的。在

class AutoRefresh(object):
    nesting = 0

    def __call__(self, f):
        def wrapper(*args, **kwargs):
            return self.proxied_call(f, args, kwargs)
        return wrapper

    def refresh(self):
        print 'refresh'

    def proxied_call(self, func, args, kwargs):
        self.nesting += 1
        result = func(*args, **kwargs)
        self.nesting -= 1
        if self.nesting == 0:
            self.refresh()
        return result

auto_refresh = AutoRefresh()

测试方法:

^{pr2}$

导致:

In a
refresh
 -
In b
In a
refresh

相关问题 更多 >

    热门问题