标签归档:global

如何制作跨模块变量?

问题:如何制作跨模块变量?

__debug__变量很方便,部分原因是它会影响每个模块。如果我想创建另一个工作方式相同的变量,我该怎么做?

变量(让我们成为原始变量,并将其称为“ foo”)不必是真正的全局变量,在某种意义上,如果我在一个模块中更改foo,则在其他模块中对其进行更新。如果我可以在导入其他模块之前设置foo,然后它们会看到相同的值,那很好。

The __debug__ variable is handy in part because it affects every module. If I want to create another variable that works the same way, how would I do it?

The variable (let’s be original and call it ‘foo’) doesn’t have to be truly global, in the sense that if I change foo in one module, it is updated in others. I’d be fine if I could set foo before importing other modules and then they would see the same value for it.


回答 0

我不以任何方式,形状或形式认可该解决方案。但是,如果您将变量添加到__builtin__模块中,则__builtin__默认情况下,就如同所有其他包含- 的模块一样,都可以访问该变量。

a.py包含

print foo

b.py包含

import __builtin__
__builtin__.foo = 1
import a

结果是打印了“ 1”。

编辑:__builtin__模块可用作本地符号__builtins__-这就是其中两个答案之间存在差异的原因。另请注意,__builtin__它已builtins在python3中重命名为。

I don’t endorse this solution in any way, shape or form. But if you add a variable to the __builtin__ module, it will be accessible as if a global from any other module that includes __builtin__ — which is all of them, by default.

a.py contains

print foo

b.py contains

import __builtin__
__builtin__.foo = 1
import a

The result is that “1” is printed.

Edit: The __builtin__ module is available as the local symbol __builtins__ — that’s the reason for the discrepancy between two of these answers. Also note that __builtin__ has been renamed to builtins in python3.


回答 1

如果您需要一个全局的跨模块变量,也许只需简单的全局模块级变量就足够了。

a.py:

var = 1

b.py:

import a
print a.var
import c
print a.var

c.py:

import a
a.var = 2

测试:

$ python b.py
# -> 1 2

实际示例:Django的global_settings.py(尽管在Django应用中,设置是通过导入对象使用的 django.conf.settings)。

If you need a global cross-module variable maybe just simple global module-level variable will suffice.

a.py:

var = 1

b.py:

import a
print a.var
import c
print a.var

c.py:

import a
a.var = 2

Test:

$ python b.py
# -> 1 2

Real-world example: Django’s global_settings.py (though in Django apps settings are used by importing the object django.conf.settings).


回答 2

定义一个模块(称为“ globalbaz”)并在其中定义变量。使用此“ pseudoglobal”的所有模块都应导入“ globalbaz”模块,并使用“ globalbaz.var_name”进行引用

无论更改的位置如何,此方法均有效,您可以在导入之前或之后更改变量。导入的模块将使用最新值。(我在一个玩具示例中对此进行了测试)

为了澄清起见,globalbaz.py看起来像这样:

var_name = "my_useful_string"

Define a module ( call it “globalbaz” ) and have the variables defined inside it. All the modules using this “pseudoglobal” should import the “globalbaz” module, and refer to it using “globalbaz.var_name”

This works regardless of the place of the change, you can change the variable before or after the import. The imported module will use the latest value. (I tested this in a toy example)

For clarification, globalbaz.py looks just like this:

var_name = "my_useful_string"

回答 3

我认为在很多情况下它确实有意义,并且它简化了编程,使某些全局变量在多个(紧密耦合的)模块中广为人知。本着这种精神,我想详细说明一下由需要引用全局模块的模块导入的全局模块。

当只有一个这样的模块时,我将其命名为“ g”。在其中,我为每个要视为全局变量的变量分配默认值。在使用它们的每个模块中,我都不使用“ from g import var”,因为这只会导致局部变量,该局部变量仅在导入时才从g初始化。我以g.var和“ g”的形式进行大多数引用。不断提醒我,我正在处理其他模块可能访问的变量。

如果此类全局变量的值要在模块中的某些函数中频繁使用,则该函数可以创建本地副本:var = g.var。但是,重要的是要认识到对var的分配是本地的,并且全局g.var不能在不显式引用分配中的g.var的情况下进行更新。

请注意,您还可以让模块的不同子集共享多个这样的全局变量模块,以使事情得到更严格的控制。我对全局模块使用短名称的原因是为了避免由于出现它们而使代码过于混乱。仅凭少量经验,它们仅用1个或2个字符就变得足够易记。

当x尚未在g中定义时,仍然可以对gx进行赋值,然后另一个模块可以访问gx。但是,即使解释器允许,这种方法也不是那么透明,我会避免它。由于赋值的变量名称中有错字,仍有可能意外地在g中创建新变量。有时,对dir(g)的检查对于发现此类事故可能引起的任何意外名称很有用。

I believe that there are plenty of circumstances in which it does make sense and it simplifies programming to have some globals that are known across several (tightly coupled) modules. In this spirit, I would like to elaborate a bit on the idea of having a module of globals which is imported by those modules which need to reference them.

When there is only one such module, I name it “g”. In it, I assign default values for every variable I intend to treat as global. In each module that uses any of them, I do not use “from g import var”, as this only results in a local variable which is initialized from g only at the time of the import. I make most references in the form g.var, and the “g.” serves as a constant reminder that I am dealing with a variable that is potentially accessible to other modules.

If the value of such a global variable is to be used frequently in some function in a module, then that function can make a local copy: var = g.var. However, it is important to realize that assignments to var are local, and global g.var cannot be updated without referencing g.var explicitly in an assignment.

Note that you can also have multiple such globals modules shared by different subsets of your modules to keep things a little more tightly controlled. The reason I use short names for my globals modules is to avoid cluttering up the code too much with occurrences of them. With only a little experience, they become mnemonic enough with only 1 or 2 characters.

It is still possible to make an assignment to, say, g.x when x was not already defined in g, and a different module can then access g.x. However, even though the interpreter permits it, this approach is not so transparent, and I do avoid it. There is still the possibility of accidentally creating a new variable in g as a result of a typo in the variable name for an assignment. Sometimes an examination of dir(g) is useful to discover any surprise names that may have arisen by such accident.


回答 4

您可以将一个模块的全局变量传递给另一个模块:

在模块A中:

import module_b
my_var=2
module_b.do_something_with_my_globals(globals())
print my_var

在模块B中:

def do_something_with_my_globals(glob): # glob is simply a dict.
    glob["my_var"]=3

You can pass the globals of one module to onother:

In Module A:

import module_b
my_var=2
module_b.do_something_with_my_globals(globals())
print my_var

In Module B:

def do_something_with_my_globals(glob): # glob is simply a dict.
    glob["my_var"]=3

回答 5

全局变量通常不是一个好主意,但是您可以通过分配给__builtins__

__builtins__.foo = 'something'
print foo

同样,模块本身是可以从任何模块访问的变量。因此,如果您定义一个名为的模块my_globals.py

# my_globals.py
foo = 'something'

然后,您也可以在任何地方使用它:

import my_globals
print my_globals.foo

__builtins__通常,使用模块而不是修改模块是执行此类全局操作的更干净的方法。

Global variables are usually a bad idea, but you can do this by assigning to __builtins__:

__builtins__.foo = 'something'
print foo

Also, modules themselves are variables that you can access from any module. So if you define a module called my_globals.py:

# my_globals.py
foo = 'something'

Then you can use that from anywhere as well:

import my_globals
print my_globals.foo

Using modules rather than modifying __builtins__ is generally a cleaner way to do globals of this sort.


回答 6

您已经可以使用模块级变量执行此操作。无论从哪个模块导入模块,它们都是相同的。因此,您可以在将其放入,访问或从其他模块分配给它的任何有意义的模块中,将该变量设为模块级变量。最好调用一个函数来设置变量的值,或者使其成为某个单例对象的属性。这样,如果您最终需要在更改变量后运行一些代码,则可以这样做而不会破坏模块的外部接口。

通常,这不是一种很好的处理方法-很少使用全局变量-但我认为这是最干净的方法。

You can already do this with module-level variables. Modules are the same no matter what module they’re being imported from. So you can make the variable a module-level variable in whatever module it makes sense to put it in, and access it or assign to it from other modules. It would be better to call a function to set the variable’s value, or to make it a property of some singleton object. That way if you end up needing to run some code when the variable’s changed, you can do so without breaking your module’s external interface.

It’s not usually a great way to do things — using globals seldom is — but I think this is the cleanest way to do it.


回答 7

我想发布一个答案,在某些情况下找不到该变量。

循环导入可能会破坏模块的行为。

例如:

第一.py

import second
var = 1

第二个

import first
print(first.var)  # will throw an error because the order of execution happens before var gets declared.

main.py

import first

在这个例子中,它应该很明显,但是在大型代码库中,这确实很令人困惑。

I wanted to post an answer that there is a case where the variable won’t be found.

Cyclical imports may break the module behavior.

For example:

first.py

import second
var = 1

second.py

import first
print(first.var)  # will throw an error because the order of execution happens before var gets declared.

main.py

import first

On this is example it should be obvious, but in a large code-base, this can be really confusing.


回答 8

这听起来像修改__builtin__命名空间。去做吧:

import __builtin__
__builtin__.foo = 'some-value'

不要__builtins__直接使用(请注意额外的“ s”)-显然这可以是字典或模块。感谢ΤZnΩΤZΙΟΥ指出这一点,更多内容请点击这里

现在 foo可在任何地方使用。

我不建议一般这样做,但是使用此方法取决于程序员。

分配它必须按照上面的步骤进行,只是设置foo = 'some-other-value'只会在当前命名空间中进行设置。

This sounds like modifying the __builtin__ name space. To do it:

import __builtin__
__builtin__.foo = 'some-value'

Do not use the __builtins__ directly (notice the extra “s”) – apparently this can be a dictionary or a module. Thanks to ΤΖΩΤΖΙΟΥ for pointing this out, more can be found here.

Now foo is available for use everywhere.

I don’t recommend doing this generally, but the use of this is up to the programmer.

Assigning to it must be done as above, just setting foo = 'some-other-value' will only set it in the current namespace.


回答 9

我将此用于几个内置的原始函数,我觉得它们确实缺少了。一个示例是具有与filter,map,reduce相同的用法语义的find函数。

def builtin_find(f, x, d=None):
    for i in x:
        if f(i):
            return i
    return d

import __builtin__
__builtin__.find = builtin_find

一旦运行(例如,通过在入口点附近导入),所有模块就可以使用find(),显然,它是内置的。

find(lambda i: i < 0, [1, 3, 0, -5, -10])  # Yields -5, the first negative.

注意:当然,您可以使用过滤器和另一条线来测试零长度,或者使用减少一种奇怪的线来执行此操作,但是我始终觉得这很奇怪。

I use this for a couple built-in primitive functions that I felt were really missing. One example is a find function that has the same usage semantics as filter, map, reduce.

def builtin_find(f, x, d=None):
    for i in x:
        if f(i):
            return i
    return d

import __builtin__
__builtin__.find = builtin_find

Once this is run (for instance, by importing near your entry point) all your modules can use find() as though, obviously, it was built in.

find(lambda i: i < 0, [1, 3, 0, -5, -10])  # Yields -5, the first negative.

Note: You can do this, of course, with filter and another line to test for zero length, or with reduce in one sort of weird line, but I always felt it was weird.


回答 10

我可以使用字典来实现跨模块的可修改(或可变)变量:

# in myapp.__init__
Timeouts = {} # cross-modules global mutable variables for testing purpose
Timeouts['WAIT_APP_UP_IN_SECONDS'] = 60

# in myapp.mod1
from myapp import Timeouts

def wait_app_up(project_name, port):
    # wait for app until Timeouts['WAIT_APP_UP_IN_SECONDS']
    # ...

# in myapp.test.test_mod1
from myapp import Timeouts

def test_wait_app_up_fail(self):
    timeout_bak = Timeouts['WAIT_APP_UP_IN_SECONDS']
    Timeouts['WAIT_APP_UP_IN_SECONDS'] = 3
    with self.assertRaises(hlp.TimeoutException) as cm:
        wait_app_up(PROJECT_NAME, PROJECT_PORT)
    self.assertEqual("Timeout while waiting for App to start", str(cm.exception))
    Timeouts['WAIT_JENKINS_UP_TIMEOUT_IN_SECONDS'] = timeout_bak

启动时test_wait_app_up_fail,实际的超时时间为3秒。

I could achieve cross-module modifiable (or mutable) variables by using a dictionary:

# in myapp.__init__
Timeouts = {} # cross-modules global mutable variables for testing purpose
Timeouts['WAIT_APP_UP_IN_SECONDS'] = 60

# in myapp.mod1
from myapp import Timeouts

def wait_app_up(project_name, port):
    # wait for app until Timeouts['WAIT_APP_UP_IN_SECONDS']
    # ...

# in myapp.test.test_mod1
from myapp import Timeouts

def test_wait_app_up_fail(self):
    timeout_bak = Timeouts['WAIT_APP_UP_IN_SECONDS']
    Timeouts['WAIT_APP_UP_IN_SECONDS'] = 3
    with self.assertRaises(hlp.TimeoutException) as cm:
        wait_app_up(PROJECT_NAME, PROJECT_PORT)
    self.assertEqual("Timeout while waiting for App to start", str(cm.exception))
    Timeouts['WAIT_JENKINS_UP_TIMEOUT_IN_SECONDS'] = timeout_bak

When launching test_wait_app_up_fail, the actual timeout duration is 3 seconds.


回答 11

我想知道是否有可能避免使用全局变量的某些缺点(请参见例如http://wiki.c2.com/?GlobalVariablesAreBad通过使用类命名空间而不是全局/模块命名空间来传递变量值) 。以下代码表明这两种方法本质上是相同的。如下所述,使用类命名空间有一点优势。

以下代码片段还显示,可以在全局/模块命名空间和类命名空间中动态创建和删除属性或变量。

wall.py

# Note no definition of global variables

class router:
    """ Empty class """

我称此模块为“墙”,因为它是用来反弹变量的。它将用作临时定义空类“路由器”的全局变量和类范围属性的空间。

source.py

import wall
def sourcefn():
    msg = 'Hello world!'
    wall.msg = msg
    wall.router.msg = msg

该模块导入wall并定义一个函数sourcefn,该函数定义消息并通过两种不同的机制发出消息,一种通过全局机制,一种通过路由器函数。请注意,变量wall.msgwall.router.message是在此处首次在其各自的命名空间中定义。

目的地

import wall
def destfn():

    if hasattr(wall, 'msg'):
        print 'global: ' + wall.msg
        del wall.msg
    else:
        print 'global: ' + 'no message'

    if hasattr(wall.router, 'msg'):
        print 'router: ' + wall.router.msg
        del wall.router.msg
    else:
        print 'router: ' + 'no message'

该模块定义了一个函数destfn,该函数使用两种不同的机制来接收源发出的消息。它允许变量“ msg”可能不存在。destfn在显示变量后也将删除它们。

main.py

import source, dest

source.sourcefn()

dest.destfn() # variables deleted after this call
dest.destfn()

该模块依次调用先前定义的函数。第一次调用dest.destfn变量后wall.msgwall.router.msg不再存在。

该程序的输出为:

全球:您好,世界!
路由器:世界您好!
全局:无消息
路由器:无消息

上面的代码片段表明,模块/全局机制和类/类变量机制基本相同。

如果要共享许多变量,则可以通过使用多个wall类型的模块(例如wall1,wall2等)或通过在单个文件中定义多个路由器类型的类来管理命名空间污染。后者稍微更整洁,因此也许代表了使用类变量机制的边际优势。

I wondered if it would be possible to avoid some of the disadvantages of using global variables (see e.g. http://wiki.c2.com/?GlobalVariablesAreBad) by using a class namespace rather than a global/module namespace to pass values of variables. The following code indicates that the two methods are essentially identical. There is a slight advantage in using class namespaces as explained below.

The following code fragments also show that attributes or variables may be dynamically created and deleted in both global/module namespaces and class namespaces.

wall.py

# Note no definition of global variables

class router:
    """ Empty class """

I call this module ‘wall’ since it is used to bounce variables off of. It will act as a space to temporarily define global variables and class-wide attributes of the empty class ‘router’.

source.py

import wall
def sourcefn():
    msg = 'Hello world!'
    wall.msg = msg
    wall.router.msg = msg

This module imports wall and defines a single function sourcefn which defines a message and emits it by two different mechanisms, one via globals and one via the router function. Note that the variables wall.msg and wall.router.message are defined here for the first time in their respective namespaces.

dest.py

import wall
def destfn():

    if hasattr(wall, 'msg'):
        print 'global: ' + wall.msg
        del wall.msg
    else:
        print 'global: ' + 'no message'

    if hasattr(wall.router, 'msg'):
        print 'router: ' + wall.router.msg
        del wall.router.msg
    else:
        print 'router: ' + 'no message'

This module defines a function destfn which uses the two different mechanisms to receive the messages emitted by source. It allows for the possibility that the variable ‘msg’ may not exist. destfn also deletes the variables once they have been displayed.

main.py

import source, dest

source.sourcefn()

dest.destfn() # variables deleted after this call
dest.destfn()

This module calls the previously defined functions in sequence. After the first call to dest.destfn the variables wall.msg and wall.router.msg no longer exist.

The output from the program is:

global: Hello world!
router: Hello world!
global: no message
router: no message

The above code fragments show that the module/global and the class/class variable mechanisms are essentially identical.

If a lot of variables are to be shared, namespace pollution can be managed either by using several wall-type modules, e.g. wall1, wall2 etc. or by defining several router-type classes in a single file. The latter is slightly tidier, so perhaps represents a marginal advantage for use of the class-variable mechanism.


Python非本地语句

问题:Python非本地语句

Python nonlocal语句有什么作用(在Python 3.0及更高版本中)?

官方Python网站上没有文档,help("nonlocal")也无法使用。

What does the Python nonlocal statement do (in Python 3.0 and later)?

There’s no documentation on the official Python website and help("nonlocal") does not work, either.


回答 0

比较一下,不使用nonlocal

x = 0
def outer():
    x = 1
    def inner():
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 0

对此,使用nonlocal,其中inner()x是现在还outer()x

x = 0
def outer():
    x = 1
    def inner():
        nonlocal x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 2
# global: 0

如果要使用global,它将绑定x到正确的“全局”值:

x = 0
def outer():
    x = 1
    def inner():
        global x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 2

Compare this, without using nonlocal:

x = 0
def outer():
    x = 1
    def inner():
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 0

To this, using nonlocal, where inner()‘s x is now also outer()‘s x:

x = 0
def outer():
    x = 1
    def inner():
        nonlocal x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 2
# global: 0

If we were to use global, it would bind x to the properly “global” value:

x = 0
def outer():
    x = 1
    def inner():
        global x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 2

回答 1

简而言之,它使您可以将值分配给外部(但非全局)范围内的变量。有关所有血腥细节,请参阅PEP 3104

In short, it lets you assign values to a variable in an outer (but non-global) scope. See PEP 3104 for all the gory details.


回答 2

谷歌搜索“ python nonlocal”发现了该提案PEP 3104,该提案完整描述了该语句背后的语法和推理。简而言之,它的作用与global声明完全相同,不同之处在于,它用于引用既不全局也不局部于函数的变量。

这是您可以执行此操作的简短示例。可以重写计数器生成器以使用它,以便它看起来更像是带有闭包的语言惯用法。

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

显然,您可以将其编写为生成器,例如:

def counter_generator():
    count = 0
    while True:
        count += 1
        yield count

但是,尽管这是完全习惯用的python,但对于初学者来说,第一个版本似乎更加明显。通过调用返回的函数正确使用生成器是一个常见的困惑点。第一个版本显式返回一个函数。

A google search for “python nonlocal” turned up the Proposal, PEP 3104, which fully describes the syntax and reasoning behind the statement. in short, it works in exactly the same way as the global statement, except that it is used to refer to variables that are neither global nor local to the function.

Here’s a brief example of what you can do with this. The counter generator can be rewritten to use this so that it looks more like the idioms of languages with closures.

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

Obviously, you could write this as a generator, like:

def counter_generator():
    count = 0
    while True:
        count += 1
        yield count

But while this is perfectly idiomatic python, it seems that the first version would be a bit more obvious for beginners. Properly using generators, by calling the returned function, is a common point of confusion. The first version explicitly returns a function.


回答 3

@ooboo:

它与源代码中的参考点“最接近”。这称为“词法作用域”,现在已经有40多年的历史了。

Python的类成员确实在名为的字典中,__dict__并且无法通过词法作用域来访问。

如果您未指定,nonlocal而是这样做x = 7,它将创建一个新的局部变量“ x”。如果您指定nonlocal,它将找到“最近”“ x”并分配给它。如果指定nonlocal并且没有“ x”,它将给您一条错误消息。

关键字global在我看来一直很奇怪,因为它会很乐意忽略除最外面的一个以外的所有其他“ x”。奇怪的。

@ooboo:

It takes the one “closest” to the point of reference in the source code. This is called “Lexical Scoping” and is standard for >40 years now.

Python’s class members are really in a dictionary called __dict__ and will never be reached by lexical scoping.

If you don’t specify nonlocal but do x = 7, it will create a new local variable “x”. If you do specify nonlocal, it will find the “closest” “x” and assign to that. If you specify nonlocal and there is no “x”, it will give you an error message.

The keyword global has always seemed strange to me since it will happily ignore all the other “x” except for the outermost one. Weird.


回答 4

help(’nonlocal’)nonlocal语句


    nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*

nonlocal语句使列出的标识符引用最近的封闭范围中的先前绑定的变量。这很重要,因为绑定的默认行为是首先搜索本地命名空间。该语句允许封装的代码在全局(模块)范围之外的本地范围之外重新绑定变量。

nonlocal与语句中列出的名称不同,语句中 列出的名称global必须引用封闭范围内的预先存在的绑定(不能明确确定应在其中创建新绑定的范围)。

nonlocal语句中列出的名称不得与本地范围内的现有绑定冲突。

也可以看看:

PEP 3104-访问外部作用域中
的名称nonlocal语句的规范。

相关帮助主题:全局,NAMESPACES

资料来源:Python语言参考

help(‘nonlocal’) The nonlocal statement


    nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*

The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.

Names listed in a nonlocal statement, unlike to those listed in a global statement, must refer to pre-existing bindings in an enclosing scope (the scope in which a new binding should be created cannot be determined unambiguously).

Names listed in a nonlocal statement must not collide with pre- existing bindings in the local scope.

See also:

PEP 3104 – Access to Names in Outer Scopes
The specification for the nonlocal statement.

Related help topics: global, NAMESPACES

Source: Python Language Reference


回答 5

引用《Python 3参考》

非本地语句使列出的标识符引用最近的包围范围中的先前绑定的变量(全局变量除外)。

如参考文献中所述,如果有多个嵌套函数,则仅修改最近的封闭函数中的变量:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        x = 2
        innermost()
        if x == 3: print('Inner x has been modified')

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Inner x has been modified

“最近”变量可以相隔几个级别:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Outer x has been modified

但是它不能是全局变量:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    inner()

x = 0
outer()
if x == 3: print('Global x has been modified')

# SyntaxError: no binding for nonlocal 'x' found

Quote from the Python 3 Reference:

The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals.

As said in the reference, in case of several nested functions only variable in the nearest enclosing function is modified:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        x = 2
        innermost()
        if x == 3: print('Inner x has been modified')

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Inner x has been modified

The “nearest” variable can be several levels away:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Outer x has been modified

But it cannot be a global variable:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    inner()

x = 0
outer()
if x == 3: print('Global x has been modified')

# SyntaxError: no binding for nonlocal 'x' found

回答 6

a = 0    #1. global variable with respect to every function in program

def f():
    a = 0          #2. nonlocal with respect to function g
    def g():
        nonlocal a
        a=a+1
        print("The value of 'a' using nonlocal is ", a)
    def h():
        global a               #3. using global variable
        a=a+5
        print("The value of a using global is ", a)
    def i():
        a = 0              #4. variable separated from all others
        print("The value of 'a' inside a function is ", a)

    g()
    h()
    i()
print("The value of 'a' global before any function", a)
f()
print("The value of 'a' global after using function f ", a)
a = 0    #1. global variable with respect to every function in program

def f():
    a = 0          #2. nonlocal with respect to function g
    def g():
        nonlocal a
        a=a+1
        print("The value of 'a' using nonlocal is ", a)
    def h():
        global a               #3. using global variable
        a=a+5
        print("The value of a using global is ", a)
    def i():
        a = 0              #4. variable separated from all others
        print("The value of 'a' inside a function is ", a)

    g()
    h()
    i()
print("The value of 'a' global before any function", a)
f()
print("The value of 'a' global after using function f ", a)

回答 7

我对“非本地”语句的个人理解(并且对不起,因为我是Python和程序设计的新手)所以,“非本地”是在迭代函数中使用全局功能的一种方式,而不是代码本身。 。如果愿意,可以在函数之间进行全局声明。

My personal understanding of the “nonlocal” statement (and do excuse me as I am new to Python and Programming in general) is that the “nonlocal” is a way to use the Global functionality within iterated functions rather than the body of the code itself. A Global statement between functions if you will.


回答 8

具有“非本地”内部函数(即嵌套内部函数)的用户可以获取外部父函数的特定变量的读取和“ 写入 ”权限。非本地只能在内部函数中使用,例如:

a = 10
def Outer(msg):
    a = 20
    b = 30
    def Inner():
        c = 50
        d = 60
        print("MU LCL =",locals())
        nonlocal a
        a = 100
        ans = a+c
        print("Hello from Inner",ans)       
        print("value of a Inner : ",a)
    Inner()
    print("value of a Outer : ",a)

res = Outer("Hello World")
print(res)
print("value of a Global : ",a)

with ‘nonlocal’ inner functions(ie;nested inner functions) can get read & ‘write‘ permission for that specific variable of the outer parent function. And nonlocal can be used only inside inner functions eg:

a = 10
def Outer(msg):
    a = 20
    b = 30
    def Inner():
        c = 50
        d = 60
        print("MU LCL =",locals())
        nonlocal a
        a = 100
        ans = a+c
        print("Hello from Inner",ans)       
        print("value of a Inner : ",a)
    Inner()
    print("value of a Outer : ",a)

res = Outer("Hello World")
print(res)
print("value of a Global : ",a)