蟒蛇;为什么不强制传递函数参数

时间:2018-06-20 09:11:34

标签: python arguments

在我看来,将要在函数内部使用的变量传递给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程序员都是有用的知识。

2 个答案:

答案 0 :(得分:3)

一个完整的答案将需要对整个语言的工作方式进行深入的解释,而这已经得到了证明-the official doc about scoping and namespaces可能是此处的最佳起点。

长话短说,在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 /并发性和{{3} },应尽可能避免。

从实际的POV中

但是,您几乎无法避免至少拥有 个“只读”全局变量(符号常量,其他函数,类,模块等),有时您还至少需要一个耦合确实会突变/重新绑定全局名称的函数(例如,考虑应用程序设置)-这里的要点是,这些函数仅应在应用程序启动时调用以定义符号常量等。

答案 1 :(得分:1)

此做法是使用在范围之外(通常为this is a very bad practice)定义的“影子名称”。许多IDE和代码检查工具都会在此处报告错误或警告。

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

但是,对于没有声明名称类型的python,则是另一回事了。如果我们不允许来自外部范围的名称,而我们突然之间将无法相互递归,并且无法实现许多编程构造!