我们已经看到Python编程的一个重要部分是调用函数来执行计算或执行其他有用的任务。我们使用过的函数示例包括print()和input()。函数对于编程非常有用,因此Python很自然地为我们提供了一种创建自己的函数的方法。
Python中函数定义的基本形式是
Def <name>(<parameter list>): <optional doc string> <statements> <return statement>
下面是一个简单的示例,演示了用户定义函数的赢博体育关键特性。
def square(x): ““”计算参数的平方”“” " result = x*x返回结果
这个示例函数计算并返回一个整数的平方。让我们仔细看看这个函数的组成部分。
函数定义的第一行设置函数的接口,包括它的名称和它接受的参数。
def广场(x):
接口声明告诉我们这个函数的名字是‘square’,它接受一个名为‘x’的参数。函数可以接受任意数量的参数。要设置多个参数,我们只需创建一个以逗号分隔的参数列表。
函数体是缩进部分。代码体包含执行计算并最终返回结果的语句。
函数体的第一行可以是一个可选的doc字符串,它是一些记录函数功能的文本。许多开发环境,如PyCharm,会查找这些文档字符串,并在您将鼠标悬停在函数名称上时显示该文档。对于doc字符串,我们总是使用特殊的Python三引号字符串格式,因为这种格式允许我们构造跨越多行的字符串。
defsquare (x): """square(x)计算它的参数x的平方。它实际上没有什么比这更多的了。当你调用这个函数时,请不要试图传递数字以外的东西。结果将难以预测。”“” result = x*x返回结果
接下来,我们将有一个或多个语句来执行一些计算。通过参数进入函数的输入在这些计算中起作用。
结果= x*x
最后一个语句是return语句,它负责返回计算的结果。
返回结果
除了我上面描述的用于定义函数的结构规则之外,在Python程序中使用函数还必须遵循一些额外的规则。
牛顿法是求函数根的一种方法。给定一个可微函数f(x)我们想找到f的一个根,也就是x的一个值使得f(x) = 0。
该方法包括以下步骤:
我们选一个点
(x0, f (x0))
求出该点处的切线方程。切线在这一点的斜率是
切线有一般形式
这条线在y = 0时与x轴相交。
为了重复这个过程,我们只需要将点x1输入到上一个公式中来生成根的下一个近似值
每次我们生成另一个近似值时,我们都可以通过简单地将其代回函数f来轻松地测试该近似值与根的接近程度。一旦|f(xn)|低于预设容差,我们就可以停止迭代。
下面是一个Python程序的代码,该程序使用牛顿方法查找函数的根
F (x) = x4 + 2x3 - 14x2 + 2x + 1
这个函数在0.4附近有一个正的实根。为了找到这个根,我们将写一个函数,它使用函数f(x)及其导数的牛顿迭代
来计算多项式f(x),f(x)更有效率,我们将使用一个特殊的技巧叫做霍纳氏法则求多项式的值。你知道霍纳法则是怎么运作的吗?
#程序的根f (x) = x ^ 4 + 2 x ^ 3 - 14 x ^ 2 + 2 + 1 #通过牛顿法#定义函数及其导数def f (x):返回(((x + 2) * x-14) * x + 2) * x + 1 def fp (x):返回((4 * x + 6) * x-28) * x + 2 =输入(“输入一个起始猜根:“)x =浮动(x) y = f (x)公差= 10 e-6 y <)或y >公差:#计算f (x) yp = fp (x) #做一个轮牛顿法x = x - y / yp y = f (x)打印(根估计是,x)
大多数编程系统都包含有用的函数库,Python也不例外。例如,为了使用标准的数学函数,如exp(x)或sin(x),我们在程序的顶部放置一个import语句来导入数学模块。
导入数学
我们可以使用该模块中的任何函数,如exp()、sin()或sqrt(),只需在其名称前加上我们从其导入的模块的名称。
Print ('exp(3.3) = ',math.exp(3.3))
或者,您可以使用import语句的变体,仅从模块导入特定函数。如果使用这种方法,可以使用这些函数名,而不需要在它们前面加上模块名。
从math导入sin, cos print('sin(1.43) = ',sin(1.43))
牛顿法有广泛的赢博体育。在本练习中,我们将最新体育赛事资讯、实时赔率分析及在线投注平台探索其中一个赢博体育程序。
许多数学函数可以在其他函数的基础上计算。一个例子是函数f(x) = ln x。定义自然对数函数的一种方法是将自然对数表示为方程的解。考虑这个等式
X = et
数学上,这个方程的解是t = lnx。
构建一个程序,使用这个方程和牛顿法来计算lnx。下面是你的程序应该做的。
math.log (x)
看看你得到的值有多接近实际值。作为编写函数的练习,让我们看看是否可以构造自己的函数来计算exp(x)。这样做的关键是exp(x)的幂级数表达式:
这是一个可以计算这个幂级数的函数的初稿。
Def exp1(x): sum = 1对于n在范围(1,16):sum += x**n/math.factorial(n)返回sum
由于幂级数的和是一个无限的和,我们将不得不满足于一个有限的近似。我通过试错法确定了n = 15的截止值,因为这样可以用最少的求和项产生最好的结果。下面是一个简单测试程序的一些输出,它证实了这一点。
Math.exp (0.5)= 2.0137527074704766 exp1(0.5)= 2.0137527074704766 . (0.3)= 1.3498588075760032
接下来,我们介绍一个简单的优化。由于x**n和math.factorial(n)的计算成本都很高,因此我们利用了求和中连续项之间的简单关系。
这意味着我们可以很容易地从它之前的项计算和中的每一个新项。
下面是使用这种优化的exp函数的一个版本。
defexp2 (x): ““”指数函数的更精细的版本。”“” sum = 1 + x term = x,对于range(2,16)中的n: term = term*x/n sum += term返回sum
下面是一个快速的测试运行,以确认这当然产生相同的数值结果与早期的,效率较低的版本。
Math.exp (0.3)= 1.3498588075760032 exp1(0.3)= 1.349858807576003 exp2(0.3)= 1.349858807576003 exp2(0.3)= 2.0137527074704766 exp1(0.5)= 2.0137527074704766 exp2(0.5)= 2.0137527074704766
我们的指数计算函数似乎工作得很好,但它还有最后一个严重的弱点。幂级数近似的问题在于,它们对赢博体育x值的收敛性都不一样。这里有另一个测试表明,当我们代入一个更大的x时,近似会变得更差。
Math.exp (3.3)= 27.112638920657883
当输入x变大时,我们可以通过增加和中的项数来解决这个问题。相反,我要采取另一种策略。由于exp2对于输入x在0到1的范围内似乎做得很好,所以技巧是将给定的任何x映射到该范围内。我们可以通过以下策略做到这一点:
Exp (x) = Exp (x/2n))2n
(exp(x/2n))2n = (exp(x/2n))2)2n-1
现在是指数计算函数的最终版本它利用了这个策略。
def exp3(x): "“ exp的最终版本-适用于更大范围的x。”“#最初我们使用x的绝对值z = math.fabs(x) #计算最小的n,使z/2**n <= 1 n = 1而z > 1: n += 1 z/ = 2.0 #因为z现在在0 <= z <= 1的范围内,exp2将#做得很好结果= exp2(z) #因为现在结果= exp(z/2**n),为了计算exp(z) #我们现在需要计算结果**(2**n)。我们通过重复平方结果来实现这一点,因为# (result**2)**(2**(n-1)) = result**(2**n)而n > 1: result = result*result n- = 1 #最后,我们处理负x的情况。if(x < 0):返回1/result else:返回结果
一个测试运行证实了这比exp2要好得多:
Math.exp (3.3)= 27.112638920657883 exp2(3.3)= 27.11262722548732 exp3(3.3)= 27.112638920657805
当程序变得更大、更复杂时,我们会想要开始将有用的函数组织到模块中,以便导入到程序中。在下一个例子中,我将编写一组处理素数的有用函数,然后将这些函数导入到一个简单的测试程序中。
首先,这是包含有用函数定义的模块:
defisprime (n,known_primes): "“”测试n是否为质数。第二个参数必须是一个质数列表,其中包括赢博体育小于根号n的质数。“”“对于known_primes中的p:如果p*p > n:返回True如果n % p == 0:返回False返回True def primeFactors(n,primes): ”“”计算并返回n的素数因子列表。"“” factors = [] x = n对于素数中的p:而x % p == 0: factors.append(p) x = x//p如果x >: 1: factors.append(x)返回factors deffindprimes (m,n,素数):“”"构造并返回一个小于n的赢博体育素数的列表。素数必须是小于或等于m的素数的种子列表。myprime = prime .copy()对于范围(m,n)中的num:如果isPrime(num, myprime)而不是myprime中的num: myprime .append(num)返回myprime
下面是使用该模块中函数的测试程序。
from prime_stuff import * p = [2,3,5,7] allPrimes = findPrimes(10,100,p) x = int(输入(‘输入2到10000之间的整数:’))如果isPrime(x,allPrimes): print(str(x) + ‘是素数。’)否则:factors = primeFactors(x,allPrimes) print(str(x) + ‘不是素数。’)print(“它的因子是”+ str(factors))