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

python为什么传递函数参数不是强制性的,python,arguments,Python,Arguments,在我看来,在python中,将要在函数中使用的变量传递给该函数并不是强制性的 此代码: 在没有错误或警告的情况下为我提供此输出: ['this', 'is', 'a', 'list'] ['this', 'is', 'a', 'list', 'asdf'] ['this', 'is', 'a', 'list', 'asdf', 'qwer'] ['this', 'is', 'a', 'list', 'asdf', 'qwer'] 我很惊讶没有提出例外情况。这是因为在我看来,允许函数使用未传递给

在我看来,在python中,将要在函数中使用的变量传递给该函数并不是强制性的

此代码:

在没有错误或警告的情况下为我提供此输出:

['this', 'is', 'a', 'list']
['this', 'is', 'a', 'list', 'asdf']
['this', 'is', 'a', 'list', 'asdf', 'qwer']
['this', 'is', 'a', 'list', 'asdf', 'qwer']
我很惊讶没有提出例外情况。这是因为在我看来,允许函数使用未传递给它们的变量会使该函数与其他代码的交互变得非常严重。 据我所知,函数的全部要点是将程序分解为几个小部分,这些小部分与代码的其余部分进行了明确的交互

问题: 为什么python允许在函数中使用尚未传递给该函数的变量

其他信息: 示例中代码过多的原因是这个线程 其中,公认的答案声称,只有当被调用函数没有修改或重命名变量时,才允许使用未经批准的变量,至少我理解是这样的,上面的代码对此进行了反例


我理解这个问题是主观的或基于观点的,因为它是一个为什么。。。问题,但我觉得这是如此基本,必须有某种共识的论点。此外,对于许多新的python程序员来说,这将是非常有用的知识。

这种做法使用的是在范围外和一般情况下定义的阴影名称。许多IDE和代码检查工具将在此处报告错误或警告


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


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

一个完整的答案需要对整个语言的工作原理进行深入的解释,这已经被记录在案——这可能是最好的起点

长话短说,在Python中,所有东西都是一个对象——包括函数、类和模块——并且函数、模块和类没有不同的名称空间。在下面的代码中:

FOO_FACTOR = 2

def foo(arg):
    return bar(arg) * FOO_FACTOR

def bar(arg):
    return arg + 3
在foo中,bar实际上是一个全局变量,就像foo_因子一样。如果函数不允许访问全局范围内的名称,那么您必须明确地传递bar和FOO_因子,如果您需要一个特殊的声明来访问全局变量,那么每次函数使用另一个函数、类或模块时,您都必须编写大量的样板代码,至少可以说这是非常不切实际的

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

嗯,重新绑定或者甚至只是改变非本地名称确实会导致很多问题——wrt/代码的可读性、可测试性等,但是wrt/并发性和,应该尽可能避免


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

。。。不修改。。。变量。我想你误解了链接的答案。列表是可变的,因此更改它们不会导致它们被重新绑定到名称,它仍然是同一个对象。如果您试图增加一个不可变的全局整数,而没有全局变量,那么它将抛出一个错误。全局变量的要点是它们几乎在模块范围内的任何地方都可以访问,这有时是有用的,而不是Python的独特功能,例如R is similarGlobal variables是一个广泛使用的构造。在你的情况下,一个是没有令人信服的需要使用。我发现这种期望有些争议,即Python解释器或任何其他动态语言都应该检测到这种情况。对于这种严格的语言,其他语言更适合。你可能想重新阅读更多的背景。实际上,许多不是所有的动态类型语言都允许这种行为=这与打字很少相关。你可以在C语言、C++语言、Pascal语言等中使用全局变量,实际上在几乎所有的过程语言中都是如此。如果在声明之前在函数中使用变量/函数,则会收到错误/警告。依我看,这更接近于OP在动态类型语言中寻找的行为,解释器在函数定义时不需要知道实际名称 现在我明白了你的答案,但是你写的方式很不清楚,可能会误导编程新手,因此我的评论。
FOO_FACTOR = 2

def foo(arg):
    return bar(arg) * FOO_FACTOR

def bar(arg):
    return arg + 3