2

我正在尝试在 Python 2.7 中创建一个示例程序,该程序在两个函数之间保存/共享状态。你调用一个函数,下次调用函数时,它应该记住之前的值。这是我当前的代码:

def stuff():
    global x 
    x = 100
    def f():
        global x
        x = x * 2
        return x
    def g():
        global x
        x = x * 4
        return x
    return (f, g)

a,b = stuff()
print(a());

此代码有效,但问题是x不能将其视为...范围之外的全局变量stuff()(这就是首先将 x 嵌入其中的全部意义stuff())。那么,将x是全球性的,还是本地化的stuff()

4

4 回答 4

2

在 Python 3.x 中,您可以使用nonlocal语句:

def stuff():
    x = 100
    def f():
        nonlocal x
        x = x * 2
        return x
    def g():
        nonlocal x
        x = x * 4
        return x
    return f, g

>>> a, b = stuff()
>>> a()
200
>>> b()
800
>>> a()
1600
于 2013-10-10T05:08:47.727 回答
2

如果您需要支持 python 2.X,@georgek 的答案是最好的,但是很多人没有意识到您可以为函数添加属性。一个常见的习惯用法是使用单个元素的列表来保存变量。

def stuff():
    x = [100]
    def g():
        x[0] = x[0]*2
        return x[0]
    def h():
        x[0] = x[0]*4
        return x[0]
    return (g,h)
a, b = stuff()
print(a())

这是有效的,因为您永远不会在内部范围内分配给 x 本身,因此它不会重新绑定变量并隐藏闭包。

于 2013-10-10T06:00:00.483 回答
1

最简单和最简单的解决方案,使用一个类:

class stuff(object):
    x = 100
    def f(self):
        self.x = self.x * 2
        return self.x

    def g(self):
        self.x = self.x * 4
        return self.x

结果:

>>> s = stuff()
>>> s.f()
200
>>> s.g()
800

您想完全阻止人们从x函数外部访问。在 Python 中这样做的方法是在它前面加上下划线:

class stuff(object):
    _x = 100
    def f(self):
        self._x = self._x * 2
        return self._x

    def g(self):
        self._x = self._x * 4
        return self._x

这告诉其他 Python 程序员它是内部的,除非风险自负,否则不要访问它。你似乎甚至想阻止这种情况,但你不能。您甚至可以在 Python 3 非本地示例中访问闭包:

def stuff():
    x = 100
    def f():
        nonlocal x
        x = x * 2
        return x

    return f

>>> a = stuff()
>>> a()
200
>>> a()
400
>>> a.__closure__[0].cell_contents
400

所以你并没有阻止任何人摆弄它,你只是让摆弄它变得晦涩难懂。并且更有可能失败。因此,您最终只会让所有相关人员的事情变得更加困难。

于 2013-10-10T05:11:39.427 回答
0

您可以使用没有全局的函数:

>>> def f():
...     f.x = 100
...     def g():
...             f.x = f.x * 2
...             return f.x
...     def h():
...             f.x = f.x * 4
...             return f.x
...     return (g, h)
...
>>> a, b = f()
>>> a()
200
>>> b()
800
>>> a()
1600
>>>
于 2013-10-10T05:24:16.710 回答