返回介绍

函数陷阱

发布于 2024-01-29 22:24:16 字数 1497 浏览 0 评论 0 收藏 0

既然已经接近函数介绍的尾声,让我们来看一些常见的陷阱。函数有些你想不到的陷阱。它们都很少见,而有些在最新版本中已经从语言中完全消失,但多数都会让新的用户栽跟头。

本地变量是静态检测的

正如我们所知道的一样,Python定义的在一个函数中进行分配的变量名是默认为本地变量的,它们存在于函数的作用域并只在函数运行时存在。Python是静态检测Python的本地变量的,当编译def代码时,不是通过发现赋值语句在运行时进行检测的。这导致了在Python新闻组中入门者最为常见的陷阱之一。

一般来说,没有在函数中赋值的变量名会在整个模块文件中查找。

这里,函数中的X被解析为模块中的X。但是如果在引用之后增加了一个赋值语句,看看会发生什么。

你得到了一个未定义变量名的错误,但其原因是微妙的。在交互模式下输入或从一个模块文件中导入时,Python读入并编译这级代码。在编译时,Python看到了对X的赋值语句,并且决定了X将会在函数中的任一地方都将是本地变量名。但是,当函数实际运行时,因为在print执行时赋值语句并没有发生,Python告诉你正在使用一个未定义的变量名。根据其变量名规则,本地变量X是在其被赋值前就使用了。实际上,任何在函数体内的赋值将会使其成为一个本地变量名。Import、=、嵌套def、嵌套类等,都会受这种行为的影响。

产生这种问题的原因在于被赋值的变量名在函数内部是当作本地变量来对待的,而不是仅仅在赋值以后的语句中才被当做是本地变量。实际上,前一个例子是最含糊不清的:是希望打印一个全局变量X之后创建一个本地变量X,还是这真的是一个程序错误?因为Python会在函数中将X作为本地变量,它就是一个错误。如果你真的想要打印全局变量X,需要在一个global语句中声明这一点。

记住,尽管这样,这一位置的赋值语句同样会改变全局变量X,而不是一个本地变量。在函数中,不可能同时使用同一个简单变量名的本地变量和全局变量。如果真的是希望打印全局变量,并在之后设置一个有着相同变量名的本地变量,导入上层的模块,并使用模块的属性标记来获得其全局变量。

点号运算(.X这部分)从命名空间对象中获取了变量的值。交互模式下的命名空间是一个名为__main__的命名空间,所以__main__.X得到了全局变量版本的X。如果还不够清楚的话,请查看第17章。

在Python最近的版本中,已经针对这种情况发布了更为专用的"unbound local"错误消息来改进这一问题,如前面的示例列表所示(它用来直接引起一个通用的名称错误);然而,这个陷阱仍然普遍出现。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文