Python 3.x 覆盖LGB范围规则? 我是Python的新手,在C和C++中有丰富的经验。我经常遇到的一个问题是希望能够在函数中引用全局变量,如下所示: # first_time needs to be referenced within foo, but could also # be modified by a different function, or from the global scope, # so I try to define it globally first_time = True def foo(): if (first_time): first_time = False foo()

Python 3.x 覆盖LGB范围规则? 我是Python的新手,在C和C++中有丰富的经验。我经常遇到的一个问题是希望能够在函数中引用全局变量,如下所示: # first_time needs to be referenced within foo, but could also # be modified by a different function, or from the global scope, # so I try to define it globally first_time = True def foo(): if (first_time): first_time = False foo(),python-3.x,scope,Python 3.x,Scope,Python给出了一个错误,我确实理解我是如何违反了: 更新:我找到了部分解决方案,但我不喜欢: def foo(): global first_time if (first_time): first_time = False first_time = True foo() 我不喜欢这个解决方案的地方是,我想在声明它的同一行上初始化它,但Python似乎不允许我这样做 此外,它不允许我在另一个函数中执行相同的操作: def bar(): gl

Python给出了一个错误,我确实理解我是如何违反了:

更新:我找到了部分解决方案,但我不喜欢:

def foo():
    global first_time
    if (first_time):
        first_time = False

first_time = True     
foo()
我不喜欢这个解决方案的地方是,我想在声明它的同一行上初始化它,但Python似乎不允许我这样做

此外,它不允许我在另一个函数中执行相同的操作:

def bar():
    global first_time
    if (first_time):
        first_time = False
是否有一种方法可以在函数外部声明和初始化它,以便多个函数可以检查和更新它

从局部范围创建全局变量是可能的,尽管这样做被认为有点不合语法:

def foo():
    if not 'first_time' in globals():
        globals()['first_time'] = True
    else:
        global first_time
    if (first_time):
        first_time = False
globals()
是一个包含所有全局名称的字典(在shell中键入
globals()
会提供信息)。你可以写信给它。对于
foo

>>> first_time
Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    first_time
NameError: name 'first_time' is not defined
>>> foo()
>>> first_time
False
第一次 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 第一次 NameError:未定义名称“首次” >>>foo() >>>第一次 错误的
您误解了Python的
全局
关键字的作用

它不声明全局变量。相反,它确保在当前代码块中,在全局范围而不是本地范围中搜索提供的标识符。(法院未能解释这一区别)

例如,如果
global
实际在全局范围内声明了一个变量,则以下代码将起作用:

def bar():
    global foo
    foo = 1

print(foo)
但它会产生:

Traceback (most recent call last):
  File "./test.py", line 5, in <module>
    print(foo)
NameError: name 'foo' is not defined
这将产生预期的
17

更新

然而,一般来说,全局变量是不受欢迎的。根据具体情况,可能有更好的方法

Python中一个鲜为人知的诀窍是,可以将属性放在方法上(这是方法是对象这一事实的结果):

输出
5
6

这样,
foo
就不是全局的,它仅限于
bar
的名称空间,但仍然可以通过
bar.foo
全局访问!如果
foo
本质上属于
bar
,但需要全局访问,那么这是一个非常好的解决方案

一个简单但更具体的例子说明了这一点的用处:假设您有一个方法
print()
,如下所示:

def print(document, printer=None):
    printer = printer or print.printer
    printer.send(document)
    print.jobcount += 1 
print.printer = get_default_printer()
print.jobcount = 0
然后你可以:

  • 使用
    Print(doc)
  • 使用
    Print(doc,printer=some\u printer)打印到特定打印机上
  • 将默认打印机设置为
    print.printer=some_printer
  • 并使用
    print.jobcount
只是不要实际命名您的方法
print()
,因为它已经是一个内置方法;-)

不过,这种方法可能最适合小事情。如果无法控制,我更喜欢用类来封装这些东西,即使我只是使用静态方法:

class Print:
    printer = get_default_printer()
    jobcount = 0

    def print(document, printer=None):
        printer = printer or Print.printer
        printer.send(document)
        Print.jobcount += 1

因此,您可以执行
Print.Print(doc)
Print.jobcount
等操作。

首次全局打印;first_time=True
但这很难看。为什么要麻烦?但是,请注意,这样做不会在全局范围内创建变量。如果我需要在第二个函数中使用相同的变量执行相同的操作,则也没有帮助,请参见上面的更新。如果
foo
更改了全局变量,则更改在
栏中可见,反之亦然。我不确定你看到了什么问题。你能解释一下吗?我假设在两个不同的函数中定义first_time,都使用global关键字,会导致错误。事实上,它工作得很好,所以这就是共享的解决方案。然后我必须在foo和bar之外对其进行初始化,但是在它们被定义之后。了解globals()字典非常有帮助,但正如你所说,它似乎不太符合语法。到目前为止,我找到的最好的解决方案是在使用它的每个函数中声明它是全局的。那是蟒蛇吗?这对我来说似乎有点难看。在全局范围内声明一个全局变量肯定更像python。我甚至犹豫是否发布我的答案(但是,正如你所说,了解
globals()
)是件好事。美学是主观的。和许多事情一样,Python也是后天习得的。如果您的口味与C/C++相适应,那么需要一些时间来适应当地的口味。在Python shell中键入
导入此
,以获得一些风味。我逐渐欣赏Python(超过C/C++),原因有很多:1)我不必做太多的内务管理,特别是内存和指针管理2)语言的丰富性,它取代了C/C++3)中的函数/方法调用,一系列令人难以置信的模块可以完成各种有用的事情,因此我不再需要编写和支持自己的运行时库。但是,C的速度很难被打败。我有时用Python制作算法原型,然后用编译语言编写它们。也可以混合使用C和Python(例如,使用
ctypes
)来充分利用这两个世界。在今天的计算机上,Python的速度足够快,但很好的一点是,您可以为Python编写速度关键型代码的C。我想这就是我要寻找的,并且尽可能接近干净和Python风格。我确实误解了“全球”的做法。我更喜欢在顶部声明全局(不带该关键字),并将其定义为对每个全局中要使用的全局的引用。是的,文本和代码示例简洁明了。@MarkColan我编辑了我的答案,以包含一些您可能感兴趣的选项:)
def bar():
    bar.foo += 1
bar.foo = 5

print(bar.foo)
bar()
print(bar.foo)

bar.foo = 1
def print(document, printer=None):
    printer = printer or print.printer
    printer.send(document)
    print.jobcount += 1 
print.printer = get_default_printer()
print.jobcount = 0
class Print:
    printer = get_default_printer()
    jobcount = 0

    def print(document, printer=None):
        printer = printer or Print.printer
        printer.send(document)
        Print.jobcount += 1