簡體   English   中英

Python3 globals()和locals()內容

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

在我的Python3學習中,在嘗試globals()和locals()的同時,我制作了一個非常基本的獨立Python程序,並收到了需要我作專家解釋的結果

然后,我在Python程序(任何)中執行了相同的2個函數,並在程序中收到了許多(所有?)值的列表,無論該聲明是局部的還是全局的或非全局的。

我的理解是globals()函數包含所有聲明為globals的值的列表(與locals相同),但是根據我的觀察,結果顯示出一些不同。

誰能解釋我看到的內容以及原因?

這是程序和結果:

python程序:

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

結果(對於上述兩行程序):

 =============== 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__'} >>> 

簡單的解釋

globals()引用當前模塊的屬性字典。 locals()引用函數/代碼片段中的當前局部變量。

設置變量只會更改locals() (除非您以其他方式使用globalnonlocal關鍵字告訴python。)

這是一個例子

默認情況下,模塊范圍全局變量與本地變量相同:

>>> globals() is locals()
True

由於在這種情況下全局變量是本地變量,因此修改本地變量也會修改全局變量。

如果創建函數並查看其中的本地人,您會發現本地人會有所不同

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

更改函數局部變量時,局部變量將自動更新

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

創建新類時也會發生類似的情況

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

更深入的解釋

如果您想知道為什么全局變量和局部變量是它們的使用方式,那么讓我們看看在Python的幕后發生了什么。

一些基礎工作

在某個時候,所有python代碼都通過了等同於evalexec函數的代碼。 這些函數接受三個參數: sourceglobals (默認為當前全局變量)和locals (默認為當前局部變量)。

函數globals()locals()將返回傳遞到上述evalexec函數中的所有內容。

Python Shell會做什么?

如果你這樣做

>>> print(globals())

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())")

如您所見,Python Shell有時會將globalslocals globals設置為相同的字典。

功能執行

在內部,函數執行本質上將做三件事:

  1. 解析傳遞給函數的參數,並將其添加到局部變量。
  2. 執行功能代碼
  3. 返回其結果。

這里是一個偽算法:

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

創建新課程

當使用類聲明時,所有縮進的代碼將單獨執行。

  1. 創建了一個新字典,它將用作locals()
  2. 您的代碼是由上述本地人執行的。
  3. 該類是通過本地人創建的

如果執行此代碼:

class Test:
   a = 5

這大約是發生了什么:

 # 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)

這如何映射到模塊導入

如果導入模塊,則會啟動復雜的導入機制。 這是一個簡化的概述:

  1. 解釋器將查看模塊是否已導入。
  2. 解釋器將找到文件。
  3. 然后讀取並解析文件
  4. 創建一個模塊對象。
  5. 將執行python腳本,並將其全局變量和局部變量設置為新模塊的__dict__屬性。
  6. 返回模塊對象。

它的工作原理如下:

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