python - Python; 为什么传递函数参数不是强制性的
问题描述
在我看来,将要在函数中使用的变量传递给 python 中的函数并不是强制性的。
这段代码:
def functionWithoutArgs():
print(theList)
theList.append('asdf')
print(theList)
theNewList = theList + ['qwer']
print(theNewList)
return theNewList
theList = ['this', 'is', 'a', 'list']
theLastList = functionWithoutArgs()
print(theLastList)
给我这个输出(没有错误或警告):
['this', 'is', 'a', 'list']
['this', 'is', 'a', 'list', 'asdf']
['this', 'is', 'a', 'list', 'asdf', 'qwer']
['this', 'is', 'a', 'list', 'asdf', 'qwer']
我很惊讶没有提出任何例外。这是因为(在我看来)允许函数使用尚未传递给它们的变量会严重混淆该函数与其他代码的交互方式。
据我了解,函数的全部意义在于将程序分解成小部分,这些小部分与其余代码的交互明确定义。
问题:
为什么 python 允许在尚未传递给该函数的函数中使用变量?
附加信息:
示例中代码过多的原因是这个线程
Use a Variable in a Function without Passing as an Argument
接受的答案声称仅在被调用函数不修改或重命名变量时才允许使用未传递的变量(至少据我所知),上面的代码是反例。
我知道这个问题是边缘主观或基于意见的,因为它是一个“为什么......”的问题,但我觉得这是非常基本的,因此必须对此达成某种共识。此外,对于许多新的 Python 程序员来说,这将是有用的知识。
解决方案
完整的答案需要深入解释整个语言的工作原理,这已经记录在案——关于范围和命名空间的官方文档可能是这里最好的起点。
长话短说,在 Python 中,一切都是对象——包括函数、类和模块——并且函数、模块和类没有不同的命名空间。IOW,在以下代码中:
FOO_FACTOR = 2
def foo(arg):
return bar(arg) * FOO_FACTOR
def bar(arg):
return arg + 3
in foo
,bar
实际上是一个全局变量,就像FOO_FACTOR
is 一样。如果不允许函数访问全局范围内的名称,则必须显式传递bar
and FOO_FACTOR
,如果需要特殊声明来访问全局变量,则每次函数使用另一个函数时都必须编写大量样板代码函数,类或模块,至少可以说是非常不切实际的。
允许函数使用尚未传递给它们的变量会严重混淆该函数与其他代码的交互方式。
好吧,重新绑定(甚至只是改变)非本地名称确实会导致很多问题 - wrt/ 可读性(推理代码的能力)、可测试性等,还有 wrt/ 并发性和可重入性,应该避免尽可能。
但是从实际的 POV 来看,您几乎无法避免至少拥有“只读”全局变量(符号常量、其他函数、类、模块等),有时您还需要至少几个确实会改变/重新绑定全局名称的函数(例如考虑应用程序设置) - 这里的重点是这些函数应该只在应用程序启动时调用来定义你的符号常量等。
推荐阅读
- javascript - 如何从包含三个对象的数组中获取每个对象?
- javascript - Phaser 3 中的场景有问题
- arrays - 如何在数组对象中只显示一条记录的角度问题?
- azure-devops - Azure DevOps 管道:参数中的反斜杠 - 它们是否需要转义以及如何转义?
- apache-spark - 将一个 DF 行拆分为另一个 DF 中的多行
- html - 我将如何允许用户在 Shopify 上互相付款?
- c++ - 循环遍历多维数组的第一列
- electron - 电子 - 窗口之间更简单的通信方式?
- sql - 创建查询以检查表中的任何列是否为 Null
- wix - 在 MSI/MSP 卸载过程中重新启动 Windows(通过自定义操作和 powershell)是否有风险?