我有一个multiply.py包含以下内容的文件:
from typing import NamedTuple
class Result(NamedTuple):
product: int
desc: str
def multiply(a: int, b: int) -> Result:
return Result(
product=a * b,
desc=f"muliplied {a} and {b}",
)
x=4
y=5
print(multiply(x, y))
Run Code Online (Sandbox Code Playgroud)
如果我像这样运行它,它当然会产生预期的结果:
$ python multiply.py
Result(product=20, desc='muliplied 4 and 5')
Run Code Online (Sandbox Code Playgroud)
exec不过我正在尝试使用以下函数运行它main.py:
from pathlib import Path
gl, lo = {}, {}
exec(Path("multiply.py").read_text(), gl, lo)
Run Code Online (Sandbox Code Playgroud)
这次的输出令人失望:
$ python main.py
Traceback (most recent call last):
File "main.py", line 4, in <module>
exec(Path("multiply.py").read_text(), gl, lo)
File "<string>", line 16, in <module>
File "<string>", line 9, in multiply
NameError: name 'Result' is not defined
Run Code Online (Sandbox Code Playgroud)
这是为什么?我不能在执行的代码中创建新类型吗exec?
由于您要从文档中传递本地变量和全局变量的两个不同的字典:
如果
exec获取两个单独的对象作为全局对象和局部对象,则代码将像嵌入类定义中一样执行
类体不是封闭范围,类体中定义的函数无法访问类体中定义的变量。self.这就是在方法定义中必须用来引用另一个方法的原因。
为了详细说明我的意思self,这里有一个实际运行类主体中的代码并查看其行为的示例:
In [1]: class NS:
...: from typing import NamedTuple
...:
...: class Result(NamedTuple):
...: product: int
...: desc: str
...:
...: def multiply(a: int, b: int) -> Result:
...: return Result(
...: product=a * b,
...: desc=f"muliplied {a} and {b}",
...: )
...:
...:
In [2]: NS.multiply(1, 2)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [2], line 1
----> 1 NS.multiply(1, 2)
Cell In [1], line 9, in NS.multiply(a, b)
8 def multiply(a: int, b: int) -> Result:
----> 9 return Result(
10 product=a * b,
11 desc=f"muliplied {a} and {b}",
12 )
NameError: name 'Result' is not defined
Run Code Online (Sandbox Code Playgroud)
无论如何,exec这是一个通常被误用的函数。有时它是完全没问题的,但通常情况是,当人们寻求exec/时eval,有更好的方法可以用 Python 来实现。