我有一个代码,作者声明物理常量的一些变量。然后是一个使用它们但不将这些参数作为函数参数传递的函数。
g = 9.81 # gravity (m / s^2)
m = 10 # mass (kg)
x = np.linspace(0, 1, 10)
def f1(x):
return g * m * x**2
def f2(x):
return x / m
这是最好的方式还是我应该将它们作为参数传递?
如果我这样做:
def f():
return x + y
x = 1
y = 2
当f()
被调用时,我们得到:
>>> f()
3
将变量作为参数传递并在全局模块的范围内使用它有什么区别?
def f(x, y):
return x + y
x = 1
y = 2
导致:
>>> f(x, y)
3
答案 0 :(得分:2)
以第一种方式执行此操作会严重妨碍您的功能的可重用性。
简单示例:
如果y=3
x
是[2, 4, 6]
中的任何数字时,我希望看到您的函数的结果怎么办?
在第一个例子中,您需要:
def f():
return x + y
results=[]
y = 3
x = 2
results.append(f())
x = 4
results.append(f())
x = 6
results.append(f())
# Or alternatively -- shorter but kind of redundant:
for num in [2, 4, 6]:
x = num
results.append(f())
使用第二个选项,您可以这样做:
def f(x, y):
return x + y
y = 3
x = [2, 4, 6]
results = [f(i,y) for i in x]
现在想象一下,使用f()
时会有更多的重复次数。
答案 1 :(得分:1)
简短的回答是,这是一个范围问题。你可以阅读:
http://python-textbok.readthedocs.io/en/1.0/Variables_and_Scope.html
在您的特定情况下,前一个函数使用代码中其他地方声明的变量x和y。后一个函数使用局部变量x和y。您可以调用后一个函数来生成不同的值(即f(2,3)将打印5),而前一个函数将始终为代码中其他位置定义的x和y输出x + y。
所以第一个函数依赖于x和y在别处定义,而后者在内部定义它们并避免与其他代码混淆,因此我们更喜欢后者的函数。
答案 2 :(得分:1)
简单的答案是python不容易修改函数范围之外的值(在这种情况下,你只是阅读它们,所以它工作正常)。
更好的答案是传递变量是首选,因为它是更好的软件设计。全局状态具有许多代码段可访问的变量,而不会彼此分离。全局状态是糟糕的设计,因为如果代码的某一部分对状态进行了意外更改(突然中断了您正在编写的代码部分),则很难找到错误的来源。
最好正确封装变量,以防止它们泄漏到任何不应该泄漏的地方。传递价值就像制作一根管子,将它们安全地运送到需要的地方。它还使跟踪错误更容易,因为您只需要找到程序停止工作的代码部分(一个函数,一个对象,或者可能是与Internet的连接),并且您可以在不了解其余部分的情况下修复它。代码正在做。
传递参数还可以通过传递不同的数据来更容易地更改函数的行为。当你需要全局状态时,处理它的最好方法是在对象中携带变量,以及明确定义的方法来修改它们(类方法)。
封装有助于程序员通过简化这些系统的部分来管理极其庞大和复杂的系统。违反封装是一种使调试成为噩梦的快捷方法,即使似乎更容易。如果你像这样把它的内容拉出来,为什么首先使用一个函数?
在示例代码中,模块足够小,不需要良好的设计。在一个更大的项目(> 50行)中,最好应用优秀的设计和重构,以便在添加功能时每个部分都易于更换和调试。你会发现许多数学家和学术编码人员只关注输出。对他们来说,编码是一个稍微强大的计算器,他们通常不需要抽象。