且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

我可以使用装饰器来改变Python中函数的局部范围吗?

更新时间:2023-10-28 09:11:40

呼应Hop的答案


  1. 不要这样做。

  2. 严重的是,不要做这个。 Lisp和Ruby是用于编写自己的自定义语法的更合适的语言。使用其中之一。或者找到一种更干净的方法

  3. 如果必须的话,您需要动态作用域变量,而不是词法作用域变量。

Python没有动态作用域变量,但是您可以模拟它。这是一个通过创建全局绑定来模拟它的示例,但是在退出时恢复了先前的值:

Python doesn't have dynamically scoped variables, but you can simulate it. Here's an example that simulates it by creating a global binding, but restores the previous value on exit:

http://codepad.org/6vAY8Leh

def adds_dynamic_z_decorator(f):
  def replacement(*arg,**karg):
    # create a new 'z' binding in globals, saving previous
    if 'z' in globals():
      oldZ = (globals()['z'],)
    else:
      oldZ = None
    try:
      globals()['z'] = None
      #invoke the original function
      res = f(*arg, **karg)
    finally:
      #restore any old bindings
      if oldZ:
        globals()['z'] = oldZ[0]
      else:
        del(globals()['z'])
    return res
  return replacement

@adds_dynamic_z_decorator
def func(x,y):
  print z

def other_recurse(x):
  global z
  print 'x=%s, z=%s' %(x,z)
  recurse(x+1)
  print 'x=%s, z=%s' %(x,z)

@adds_dynamic_z_decorator
def recurse(x=0):
  global z
  z = x
  if x < 3:
    other_recurse(x)

print 'calling func(1,2)'
func(1,2)

print 'calling recurse()'
recurse()

我不保证其效用或完整性以上代码。实际上,我保证它 是疯狂的,除非您希望从Python同行那里获得鞭log,否则应避免使用它。

I make no warranties on the utility or sanity of the above code. Actually, I warrant that it is insane, and you should avoid using it unless you want a flogging from your Python peers.

此代码是类似于eduffy和John Montgomery的代码,但是确保创建 z并正确地像本地变量一样还原 z,例如,请注意 other_recurse如何能够看到在其中指定的 z的绑定递归的主体。

This code is similar to both eduffy's and John Montgomery's code, but ensures that 'z' is created and properly restored "like" a local variable would be -- for instance, note how 'other_recurse' is able to see the binding for 'z' specified in the body of 'recurse'.