【问题标题】:How does this strange python decorator work这个奇怪的 python 装饰器是如何工作的
【发布时间】:2011-02-11 02:15:05
【问题描述】:

我正在查看 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找到。

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

【问题讨论】:

  • 我已经编辑了我的答案 - 现在它向您展示了与您在演示代码中的 pyFacebook 中看到的完全相同的情况。
  • 注意:不要做这个sn-p的程序员做的事情,重命名nextnext 是一个内置函数。

标签: python decorator


【解决方案1】:

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

以下示例可能会有所帮助:

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

print A().a
print A.a

更新: 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

【讨论】:

  • 这是一个闭包吗?如果不是,那有什么区别?
  • @spade78 是的。 decoratornewview 都不能从外部看到,并且只使用它们的本地范围变量。所以,它们是闭包。我不是理论家。看Wikipedia definition of closures
  • 好的,我想我明白了。 newview 是一个定义为方法的对象,该方法包含在创建 closuredecorator 范围内。 decorator 又被包含在 require_login 的范围内,从而创建了另一个闭包。然后在 decorator 的范围内,newview 对象的属性与从 require_login 方法调用传入的对象绑定,这样当 一段时间后调用 newview 对象,它已经绑定了可以使用的属性。 @alex-jg:希望这会增加对 poltos 的解释。
  • 啊哈!我现在明白了。感谢您的解释,这个小sn-p困扰了我一段时间。
猜你喜欢
  • 2011-07-25
  • 2020-10-15
  • 2016-01-06
  • 2016-01-24
  • 2020-04-08
  • 2017-11-27
  • 2021-07-11
  • 2019-10-14
  • 2011-07-05
相关资源
最近更新 更多