sách gpt4 ai đã đi

Python 内部 - 对象如何知道全局变量?

In lại 作者:行者123 更新时间:2023-11-28 21:54:34 26 4
mua khóa gpt4 Nike

我最近发现了一些有趣的行为,这让我想知道对象如何知道存在哪些全局变量。例如,假设我有一个文件“test.py”:

globalVar = 1
toDelete = 2

class Test(object):
classVar = 3

def runTest1(self):
print globalVar
print toDelete
print missingVar

def runTest2(self):
print self.classVar
print toCreate
print missingVar

然后在交互式 shell 中我这样做:

>>> import test
>>> tester = test.Test()
>>> tester.runTest1()
1
2
Theo dõi (cuộc gọi gần đây nhất là cuộc gọi cuối cùng):
Tệp "", dòng 1, trong
File "test.py", line 10, in runTest1
print missingVar
NameError: global name 'missingVar' is not defined
>>> tester.runTest2()
3
Theo dõi (cuộc gọi gần đây nhất là cuộc gọi cuối cùng):
Tệp "", dòng 1, trong
File "test.py", line 14, in runTest2
print toCreate
NameError: global name 'toCreate' is not defined

没什么奇怪的。然后我将“test.py”的前几行更改为:

globalVar = 4 
toCreate = 5

class Test(object):
classVar = 6

现在回到交互式 shell:

>>> reload(test) # test = reload(test) gives the same result 

>>> tester.runTest1()
4
2
Theo dõi (cuộc gọi gần đây nhất là cuộc gọi cuối cùng):
Tệp "", dòng 1, trong
File "test.py", line 10, in runTest1
print missingVar
NameError: global name 'missingVar' is not defined
>>> tester.runTest2()
3
5
Theo dõi (cuộc gọi gần đây nhất là cuộc gọi cuối cùng):
Tệp "", dòng 1, trong
File "test.py", line 15, in runTest2
print missingVar
NameError: global name 'missingVar' is not defined
>>> dir(test)
['Test', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'globalVar', 'toCreate', 'toDelete']

Vì thế tester 现在知道 toCreate,它在 tester 本身被创建之后出现。它仍然知道 toDelete,因为重新加载模块显然不会影响已删除的全局变量。转折点来了:

>>> import sys
>>> import importlib
>>> del(sys.modules['test']) # remove cached version
>>> test = importlib.import_module('test') # same result if I don't have 'test = '
>>> tester.runTest1()
Không có
Không có
Theo dõi (cuộc gọi gần đây nhất là cuộc gọi cuối cùng):
Tệp "", dòng 1, trong
File "test.py", line 10, in runTest1
print missingVar
NameError: global name 'missingVar' is not defined
>>> tester.runTest2()
3
Không có
Theo dõi (cuộc gọi gần đây nhất là cuộc gọi cuối cùng):
Tệp "", dòng 1, trong
File "test.py", line 15, in runTest2
print missingVar
NameError: global name 'missingVar' is not defined
>>> dir(test)
['Test', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'globalVar', 'toCreate']

từ sys.modules 中删除模块,然后重新导入模块会导致所有全局变量变为 Không có.

同样有趣的是,如果我删除 Bài kiểm trasys.modules['test'],它仍然会暂时知道变量的值。片刻之后(我假设这是模块被垃圾回收所花费的时间),值变为 Không có。重新导入模块会导致垃圾收集(或任何正在发生的事情)立即发生。

那么 tester 如何找到正在创建的新全局变量,然后一旦模块消失,为什么它仍然知道存在哪些变量,即使它不再知道它们持有什么值?

1 Câu trả lời

任何非本地名称(在当前范围内尚未分配)都被假定为全局名称。每次代码运行时都会查找该名称。

因此在运行时 名称在全局命名空间中查找,它只是一个字典。如果该名称当时不存在,则会引发 NameError 异常。

反汇编函数时可以看到这一点;使用 dis mô-đun 时显示字节码:

>>> import dis
>>> def foo():
... bar = 'baz' # local
... bar # reference the local
... baz # reference something else; e.g. a global
...
>>> dis.dis(foo)
2 0 LOAD_CONST 1 ('baz')
3 STORE_FAST 0 (bar)

3 6 LOAD_FAST 0 (bar)
9 POP_TOP

4 10 LOAD_GLOBAL 0 (baz)
13 POP_TOP
14 LOAD_CONST 0 (None)
17 RETURN_VALUE

thanh 是局部的(它被分配到 block 中),而 baz 是全局的。局部由 LOAD_FAST 引用,而全局由 LOAD_GLOBAL 引用。

为此,函数对象有一个 function.__globals__ 引用,将其链接到模块全局映射;请参阅 datamodel documentation TRONG用户定义函数部分:

>>> foo.__globals__ is globals()
ĐÚNG VẬY

Python 还在删除模块时清理全局变量;为了防止循环引用阻碍最终确定全局变量在那个时候被反弹到 Không có (尽管这种行为 changed in Python 3.4 )。但是,如果您维护对 tester 的引用,您的代码将找到那些 Không có giá trị.

Của bạn tester 实例仍然引用原始类及其方法,仍然通过它们的 function.__globals__ 引用来引用它们的模块。因此,尽管您删除了对模块的 sys.modules 引用,触发了模块清理,但 globals 字典 仍被类方法引用。这个全局字典现在包含每个全局的 Không có giá trị.

关于Python 内部 - 对象如何知道全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24020108/

26 4 0
Bài viết được đề xuất: python - 如何删除 Django Rest Api 中的集合?
Bài viết được đề xuất: python - Numpy 逐元素标准差
Bài viết được đề xuất: python - 为什么生成器不是上下文管理器?
Bài viết được đề xuất: python - 如何在循环时从 Python 列表中排除对象
行者123
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com