首页 > 编程问答 >函数有时指局部变量,有时指全局变量

函数有时指局部变量,有时指全局变量

时间:2024-07-29 06:54:08浏览次数:9  
标签:python python-2.7

我正在尝试从给定的输入变量创建一个字典。

我遇到了一个非常奇怪的行为,所以我开始调查。

我最终得出的结论是该函数有时引用局部变量,并且有时会搜索同名的全局变量。

更具体地说:

  • 当我在循环中创建字典时,它指的是 全局 变量
  • 它指的是 本地|| |当我逐一创建字典时的变量 当我在循环中创建元组列表时它指的是
  • 本地 变量 当我在循环中创建元组列表时它指的是
  • 本地 变量逐个创建元组列表 这里有一小段代码说明了这个问题:

打印输出:

x = 1
y = 2
z = 3

def func(x,y,z):
    print {var:eval(var) for var in ['x','y','z']}          # Uses globals
    print {'x':eval('x'),'y':eval('y'),'z':eval('z')}       # Uses locals
    print [(var,eval(var)) for var in ['x','y','z']]        # Uses locals
    print [('x',eval('x')),('y',eval('y')),('z',eval('z'))] # Uses locals

func(4,5,6)

我在这里缺少什么?

{'y': 2, 'x': 1, 'z': 3}
{'y': 5, 'x': 4, 'z': 6}
[('x', 4), ('y', 5), ('z', 6)]
[('x', 4), ('y', 5), ('z', 6)]

What am I missing here?


观察到的行为与列表推导式 (list comprehension) 和字典推导式 (dictionary comprehension) 中的作用域规则有关。在 Python 中,列表推导式和字典推导式会创建自己的作用域。这意味着在推导式内部定义的变量在推导式外部是不可见的。

让我们来逐行分析的代码:

  1. print {var:eval(var) for var in ['x','y','z']}

    • 这里使用字典推导式来创建一个字典。
    • eval(var) 在没有提供全局或本地命名空间的情况下被调用,它会默认使用调用它的作用域。
    • 在这种情况下,循环在 func 函数的作用域内运行,所以 eval 会在 func 函数的作用域中查找变量 x y z
    • 由于在 func 函数中定义了同名的局部变量,所以 eval 会使用这些局部变量的值。
  2. print {'x':eval('x'),'y':eval('y'),'z':eval('z')}

    • 这里没有使用推导式,而是直接创建了一个字典。
    • 和上面一样, eval 函数会默认使用调用它的作用域。
    • 所以, eval('x') eval('y') eval('z') 会分别使用 func 函数中定义的局部变量 x y z 的值。
  3. print [(var,eval(var)) for var in ['x','y','z']]

    • 这里使用了列表推导式来创建一个列表。
    • 和字典推导式一样,列表推导式也会创建自己的作用域。
    • 所以在列表推导式内部, eval(var) 会在列表推导式的作用域内查找变量。
    • 由于在列表推导式的作用域内没有定义变量 x y z ,所以 eval 会去外层作用域,也就是 func 函数的作用域中查找,并使用 func 函数中定义的局部变量的值。
  4. print [('x',eval('x')),('y',eval('y')),('z',eval('z'))]

    • 这里没有使用推导式,而是直接创建了一个列表。
    • 和第 2 点一样, eval 函数会默认使用调用它的作用域,也就是 func 函数的作用域。
    • 所以 eval('x') eval('y') eval('z') 会分别使用 func 函数中定义的局部变量 x y z 的值。

总的来说,观察到的行为是符合 Python 的作用域规则的。

重要提示: 使用 eval 函数通常是不安全的,因为它可以执行任意代码。如果需要从字符串中获取变量的值,建议使用字典或其他更安全的方法。

标签:python,python-2.7
From: 45374109

相关文章

  • 如何用Python制作Android服务?
    我想构建一个简单的Android应用程序,例如PushOver应用程序,它具有TCP服务器并接收其记录的文本消息,然后将其作为推送通知发送。这部分已经完成并且工作正常。但即使GUI应用程序关闭,我也想接收消息。我知道这是可能的,因为PushOver应用程序做到了!我想,我可能需要一......
  • Python Discord Bot 的应用程序命令的区域设置名称(多语言别名)
    如何根据用户的语言设置,使应用程序命令的名称具有不同的名称例如,如果一个用户将其discord的语言设置为英语,则用户可以看到英语的应用程序命令名称。另一方面,如果另一个用户将其不和谐语言设置为法语,则用户可以看到法语中的相同应用程序命令的名称。为此,我尝试使用ap......
  • 如何在Python中添加热键?
    我正在为游戏制作一个机器人,我想在按下热键时调用该函数。我已经尝试了一些解决方案,但效果不佳。这是我的代码:defstart():whileTrue:ifkeyboard.is_pressed('alt+s'):break...defmain():whileTrue:ifkeyboard.is_pr......
  • 在Python中解压文件
    我通读了zipfile文档,但不明白如何解压缩文件,只了解如何压缩文件。如何将zip文件的所有内容解压缩到同一目录中?importzipfilewithzipfile.ZipFile('your_zip_file.zip','r')aszip_ref:zip_ref.extractall('target_directory')将......
  • 如何在Python中从RSA公钥中提取N和E?
    我有一个RSA公钥,看起来像-----BEGINPUBLICKEY-----MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAvm0WYXg6mJc5GOWJ+5jkhtbBOe0gyTlujRER++cvKOxbIdg8So3mV1eASEHxqSnp5lGa8R9Pyxz3iaZpBCBBvDB7Fbbe5koVTmt+K06o96ki1/4NbHGyRVL/x5fFiVuTVfmk+GZNakH5dXDq0fwvJyVmUtGYA......
  • Swagger、Docker、Python-Flask: : https://editor.swagger.io/ 生成服务器 python-fl
    在https://editor.swagger.io/上您可以粘贴一些json/yaml。我正在将此作为JSON进行测试(不要转换为YAML):{"swagger":"2.0","info":{"version":"1.0","title":"OurfirstgeneratedRES......
  • 使用 Matplotlib 的 Python 代码中出现意外的控制流
    Ubuntu22.04上的此Python3.12代码的行为符合预期,除非我按q或ESC键退出。代码如下:importnumpyasnp,matplotlib.pyplotaspltfrompathlibimportPathfromcollectionsimportnamedtuplefromskimage.ioimportimreadfrommatplotlib.widgets......
  • 参考 - Python 类型提示
    这是什么?这是与在Python中使用类型提示主题相关的问题和答案的集合。这个问题本身就是一个社区维基;欢迎大家参与维护。这是为什么?Python类型提示是一个不断增长的话题,因此许多(可能的)新问题已经被提出,其中许多甚至已经有了答案。该集合有助于查找现有内容。范......
  • 我的 Python 程序中解决 UVa 860 的运行时错误 - 熵文本分析器
    我正在尝试为UVa860编写一个解决方案,但是当我通过vJudge发送它时,它一直显示“运行时错误”。fromsysimportstdinimportmathdefmain():end_of_input=Falselambda_words=0dictionary={}text_entropy=0relative_entropy=0whilenotend_of_in......
  • Python进度条
    当我的脚本正在执行某些可能需要时间的任务时,如何使用进度条?例如,一个需要一些时间才能完成并在完成后返回True的函数。如何在函数执行期间显示进度条?请注意,我需要实时显示进度条,所以我不知道该怎么办。我需要thread为此吗?我不知道。现在在执行函数......