Python闭包与语言X闭包相比有哪些限制?

2024-06-01 00:20:49 发布

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

其中X是任何支持某种闭包风格的编程语言(C#、Javascript、Lisp、Perl、Ruby、Scheme等)。

Closures in Python(与Ruby的闭包相比)中提到了一些限制,但是本文很旧,现代Python中不再存在许多限制。

看到一个具体限制的代码示例会很好。

相关问题:


Tags: 代码inyou示例风格javascript编程语言can
3条回答

与Javascript闭包相比,Python闭包的一个限制(或“限制”)是它不能用于有效的数据隐藏

Javascript

var mksecretmaker = function(){
    var secrets = [];
    var mksecret = function() {
        secrets.push(Math.random())
    }
    return mksecret
}
var secretmaker = mksecretmaker();
secretmaker(); secretmaker()
// privately generated secret number list
// is practically inaccessible

Python

import random
def mksecretmaker():
    secrets = []
    def mksecret():
        secrets.append(random.random())
    return mksecret

secretmaker = mksecretmaker()
secretmaker(); secretmaker()
# "secrets" are easily accessible,
# it's difficult to hide something in Python:
secretmaker.__closure__[0].cell_contents # -> e.g. [0.680752847190161, 0.9068475951742101]

我看到人们遇到的唯一困难是,特别是当他们试图将非功能特性(如变量重新分配和闭包)混合在一起时,当这不起作用时,他们会感到惊讶:

def outer ():
    x = 1
    def inner ():
        print x
        x = 2
    return inner
outer () ()

通常只要指出函数有自己的局部变量就足以阻止这种愚蠢。

目前,最重要的限制是不能分配给外部作用域变量。换句话说,闭包是只读的:

>>> def outer(x): 
...     def inner_reads():
...         # Will return outer's 'x'.
...         return x
...     def inner_writes(y):
...         # Will assign to a local 'x', not the outer 'x'
...         x = y
...     def inner_error(y):
...         # Will produce an error: 'x' is local because of the assignment,
...         # but we use it before it is assigned to.
...         tmp = x
...         x = y
...         return tmp
...     return inner_reads, inner_writes, inner_error
... 
>>> inner_reads, inner_writes, inner_error = outer(5)
>>> inner_reads()
5
>>> inner_writes(10)
>>> inner_reads()
5
>>> inner_error(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 11, in inner_error
UnboundLocalError: local variable 'x' referenced before assignment

在本地作用域(函数)中分配给的名称总是本地的,除非另有声明。虽然有一个“global”声明来声明一个变量是全局的,即使它被赋值给了,但是还没有这样的声明来声明所包含的变量。在Python3.0中,有一个“非本地”声明可以做到这一点。

您可以同时使用可变容器类型来解决此限制:

>>> def outer(x):
...     x = [x]
...     def inner_reads():
...         # Will return outer's x's first (and only) element.
...         return x[0]
...     def inner_writes(y):
...         # Will look up outer's x, then mutate it.      
...         x[0] = y
...     def inner_error(y):
...         # Will now work, because 'x' is not assigned to, just referenced.
...         tmp = x[0]
...         x[0] = y
...         return tmp
...     return inner_reads, inner_writes, inner_error
... 
>>> inner_reads, inner_writes, inner_error = outer(5)
>>> inner_reads()
5
>>> inner_writes(10)
>>> inner_reads()
10
>>> inner_error(15)
10
>>> inner_reads()
15

相关问题 更多 >