这个奇怪的python装饰器是如何工作的

时间:2011-02-11 02:15:05

标签: python decorator

我正在浏览pyFacebook库的源代码并找到以下代码:

def require_login(next=None, internal=None, required_permissions=None):
    def decorator(view):
        def newview(request, *args, **kwargs):
            next = newview.next
            internal = newview.internal

            try:
                fb = request.facebook
            except:
                raise ImproperlyConfigured('Make sure you have the Facebook middleware installed.')

            if internal is None:
                internal = request.facebook.internal

...           

            return view(request, *args, **kwargs)
        newview.next = next
        newview.internal = internal
        return newview
    return decorator

我试图跳过无关的代码,因此中间的省略号。完整列表可在https://github.com/sciyoshi/pyfacebook/blob/master/facebook/djangofb/__init__.py

找到

我的困惑源于第四行对嵌套函数的'next'属性的引用。我无法弄清楚newview.next的价值应该是什么,每当我自己尝试类似的实验时,我得到'函数没有属性内部'错误。但是,代码工作正如我在django项目中使用它没有问题。如果有人能向我解释这里发生了什么,那将非常高兴。

1 个答案:

答案 0 :(得分:1)

在Python中,函数内定义的变量与函数外部定义的变量不同。

以下示例可能有所帮助:

cass A:
  a = 1
  def `__init__`(self):
    self.a = 2

print A().a
print A.a

UPD: 对象 newview 在函数内部的范围是由于函数之后的定义:

newview.next = next

请记住,在Python中,函数也是对象,也可以有属性!

这是一个更有帮助的例子:

def b():
  x=b.x
  print x

b()
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "<stdin>", line 2, in b
>   AttributeError: 'function' object has no attribute 'x'
b.x = 1
b()
> 1

这里没有魔法: b()不知道它的名字。它只是在其范围内看到一个变量 b 指向自身。它可以是由

定义的一些变量 d
d = b
d.x = 1