蟒;为什么传递函数参数不是强制性的



在我看来,在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允许在尚未传递给该函数的函数中使用变量?

附加信息:
示例中代码过多的原因是此线程 在函数中使用变量而不作为参数传递 其中接受的答案声称仅当被调用的函数不修改或重命名变量(至少据我所知(时才允许使用未传递的变量,上面的代码反驳了这一点。

我知道这个问题是基于边缘主观或意见的,因为它是一个"为什么......"问题,但我觉得这太基本了,必须对此进行某种共识论证。此外,对于许多新的python程序员来说,这将是有用的知识。

一个完整的答案需要对整个语言的工作原理进行深入的解释,这已经记录在案 - 关于范围和命名空间的官方文档可能是这里最好的起点。

长话短说,在Python中,一切都是一个对象 - 包括函数,类和模块 - 并且函数,模块和类没有不同的命名空间。IOW,在以下代码中:

FOO_FACTOR = 2
def foo(arg):
return bar(arg) * FOO_FACTOR
def bar(arg):
return arg + 3

foo中,bar实际上和FOO_FACTOR一样是一个全局变量。如果不允许函数访问全局范围内的名称,则必须显式传递barFOO_FACTOR,如果您需要一个特殊的声明来访问全局变量,则必须在每次函数使用另一个函数、类或模块时编写大量样板代码,这至少可以说是不切实际的。

允许函数使用尚未传递给它们的变量 混淆了该函数如何与其他代码交互 严重。

好吧,重新绑定(甚至只是改变(非本地名称确实会导致很多问题 - wrt/可读性(推理代码的能力(,可测试性等,还有wrt/并发性和重入性,应该尽可能避免。

但是从实际的 POV 来看,您很难避免至少拥有"只读"全局变量(符号常量、其他函数、类、模块等(,有时您还需要至少几个确实会改变/重新绑定全局名称的函数(例如考虑应用程序设置( - 这里的重点是这些函数应该只在应用程序启动时调用以定义您的符号常量等。

这种做法是在范围之外使用定义的"阴影名称",一般来说,这是一个非常糟糕的做法。许多 IDE 和代码检查工具会在此处报告错误或警告。

实际上,许多(如果不是全部(动态类型语言都允许这种行为。IMO,这是因为在编写函数时,我们希望能够以我们喜欢的任何顺序编写函数。对于像 C 这样将声明和定义分开的语言,我们可以确保所有内容都在定义部分声明。

但是,对于不声明名称类型的python来说,情况就不同了。如果我们不允许来自外部范围的名称,我们突然不能有相互递归和许多编程结构!

最新更新