简体   繁体   English

Python3 globals()和locals()内容

[英]Python3 globals() and locals() contents

In my Python3 learning, while trying out globals() and locals(), I made a very basic, stand-alone Python program and received results for which I ask for expert explanation . 在我的Python3学习中,在尝试globals()和locals()的同时,我制作了一个非常基本的独立Python程序,并收到了需要我作专家解释的结果

I then executed the same 2 functions inside my Python program (any) and received a list of many (all ?) values in my program, regardless if it was declared local or global or non. 然后,我在Python程序(任何)中执行了相同的2个函数,并在程序中收到了许多(所有?)值的列表,无论该声明是局部的还是全局的或非全局的。

My understanding was that the globals() functions holds a list of all values that were declared as globals (same for locals), but according to my observation, the results show something different. 我的理解是globals()函数包含所有声明为globals的值的列表(与locals相同),但是根据我的观察,结果显示出一些不同。

Can anyone explain what I see and why? 谁能解释我看到的内容以及原因?

Here is the program and the results: 这是程序和结果:

The python program: python程序:

  print("Globals=",globals()) print("Locals=",locals()) 

The result (for the above 2-lines program): 结果(对于上述两行程序):

 =============== RESTART: /home/pi/Junk/globals_locals_test.py ========== Globals= {'__package__': None, '__spec__': None, '__loader__': <class ' _frozen_importlib.BuiltinImporter'>, '__doc__': None, '__file__': ' /home/pi/Junk/globals_locals_test.py', '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__'} Locals= {'__package__': None, '__spec__': None, '__loader__': <class ' _frozen_importlib.BuiltinImporter'>, '__doc__': None, '__file__': ' /home/pi/Junk/globals_locals_test.py', '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__'} >>> 

Simple explanation 简单的解释

globals() refers to the current modules' attribute dictionary. globals()引用当前模块的属性字典。 locals() refers to the current local variables in your function/code-snippet. locals()引用函数/代码片段中的当前局部变量。

Setting a variable will only ever change locals() . 设置变量只会更改locals() (Unless you tell python otherwise using the global or nonlocal keyword.) (除非您以其他方式使用globalnonlocal关键字告诉python。)

Here an example 这是一个例子

By default on module-scope globals is the same dict as locals: 默认情况下,模块范围全局变量与本地变量相同:

>>> globals() is locals()
True

Since globals is locals in this case, modifying the locals will also modify the globals. 由于在这种情况下全局变量是本地变量,因此修改本地变量也会修改全局变量。

If you create a function and look at locals in there, you will see that locals will differ 如果创建函数并查看其中的本地人,您会发现本地人会有所不同

>>> def test():
...    print("globals is locals:", globals() is locals())
...    print("globals:", globals())
...    print("locals:", locals())
>>> test()
globals is locals: False
globals: {'__name__': '__main__', ...}
locals: {}

Locals will automatically update when you change a function-local variable 更改函数局部变量时,局部变量将自动更新

>>> def test2():
...     print("locals 1:", locals())
...     x = 1
...     print("locals 2:", locals())
>>> test2()
locals 1: {}
locals 2: {'x': 1}

Something similar happens when creating new classes 创建新类时也会发生类似的情况

>>> class Test:
...     print("locals:", locals())
locals: {'__module__': '__main__', '__qualname__': 'Test'}

More in-depth explanation 更深入的解释

If you want to know why globals and locals are the way they are let's look at what happens under the hood of Python. 如果您想知道为什么全局变量和局部变量是它们的使用方式,那么让我们看看在Python的幕后发生了什么。

Some ground work 一些基础工作

All python code passes what equates to the eval or exec function at some point. 在某个时候,所有python代码都通过了等同于evalexec函数的代码。 These functions accept three parameters: source , globals (defaults to current globals) and locals (defaults to current locals). 这些函数接受三个参数: sourceglobals (默认为当前全局变量)和locals (默认为当前局部变量)。

The function globals() and locals() will return whatever has been passed into the eval or exec functions shown above. 函数globals()locals()将返回传递到上述evalexec函数中的所有内容。

What does the Python Shell do? Python Shell会做什么?

If you do 如果你这样做

>>> print(globals())

The REPL will internally do something along the lines of REPL将按照以下方式在内部做一些事情

# This variable stores your globals.
_my_main_module = {}

def exec_some_line(line):
    return eval(line, globals=_my_main_module, locals=_my_main_module)

# ...

exec_some_line("print(globals())")

As you can see, the Python Shell will at some point set globals and locals to the same dict. 如您所见,Python Shell有时会将globalslocals globals设置为相同的字典。

Function execution 功能执行

Internally, function execution will essentially do three things: 在内部,函数执行本质上将做三件事:

  1. Parse the arguments passed to the function and add them to the local variables. 解析传递给函数的参数,并将其添加到局部变量。
  2. Execute the code of the function 执行功能代码
  3. Return its result. 返回其结果。

Here a pseudo-algorithm: 这里是一个伪算法:

def __call__(*args, **kwargs):
    local_variables = parse_signature_with_args(args, kwargs)
    exec(function_source, function_globals, local_variables)
    return function_result

Creating new classes 创建新课程

When using the class-statement, all indented code will be executed separately. 当使用类声明时,所有缩进的代码将单独执行。

  1. a new dictionary is created that will act as locals() 创建了一个新字典,它将用作locals()
  2. Your code is executed with said locals. 您的代码是由上述本地人执行的。
  3. The class is created passing locals in 该类是通过本地人创建的

If you execute this code: 如果执行此代码:

class Test:
   a = 5

This is approximately what happens: 这大约是发生了什么:

 # 1. A new dictionary is created
 _dict = type.__prepare__()
 _dict["__module__"] = __name__
 _dict["__qualname__"] = "Test"

 # 2. Execute the code
 exec("a = 5", globals=globals(), locals=_dict)

 # 3. A class is created
 Test = type("Test", (), _dict)

How this maps to module imports 这如何映射到模块导入

If you import a module an intricate import mechanism starts. 如果导入模块,则会启动复杂的导入机制。 This is a simplified overview: 这是一个简化的概述:

  1. The interpreter will look if the module has already been imported. 解释器将查看模块是否已导入。
  2. The interpreter will find the file. 解释器将找到文件。
  3. Then the file is read and parsed 然后读取并解析文件
  4. A module object is created. 创建一个模块对象。
  5. The python script is executed and its globals and locals will be set to the new modules' __dict__ attribute. 将执行python脚本,并将其全局变量和局部变量设置为新模块的__dict__属性。
  6. The module object is returned. 返回模块对象。

It works something like this: 它的工作原理如下:

import sys
from types import ModuleType
def __import__(name):
    # 1. See if module is already imported
    if name in sys.modules:
       return sys.modules[name]

    # 2. Find file.
    filename = find_out_path_to_file(name)

    # 3. Read and parse file
    with open(filename) as f:
      script = f.read()

    # 4. Create the new module
    module = ModuleType(name)

    # 5. Execute the code of the module.
    exec(script, globals=module.__dict__, locals=module.__dict__)

    # 6. Return the new module.
    return module

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM