一、函数(function)引入
1、函数(计算机函数)是程序中一段相对独立的代码,这段代码能够实现某一项具有独立、完整的功能。指可以直接被另一段程序代码引用的程序代码。
2、函数分为系统函数和自定义函数
系统函数一般分为:
▶
\blacktriangleright
▶数学运算类函数
▶
\blacktriangleright
▶数据转换类函数
▶
\blacktriangleright
▶字符串操作类函数
▶
\blacktriangleright
▶输入输出函数
▶
\blacktriangleright
▶文件操作类函数
▶
\blacktriangleright
▶其他类函数
二、系统函数
常用的系统函数包括:import()、input()、int()、float()、print()、abs()、range()、max()、min()、pow()、format()、round()、sum()、ord()、chr()……
下面我们选择几个常见的系统函数进行讲解:
for i in range(10): #range(10)生成[0,1,2,3,4,5,6,7,8,9]列表
print(i) # 依次打印数字0-9
for a in range(1,10,2): # 步长为2
print(a) # 打印1,3,5,7,9
for b in range(10, 0, -2): # 步长为-2
print(b) # 打印10,8,6,4,2
max()函数返回给定参数的最大值,参数可以为序列。
print("max(10,20,30):" , max(10,20,30) )
# max(10,20,30): 30
print("max(10,-2,3.4):" , max(10,-2,3.4) )
# max(10,-2,3.4): 10
pow()函数返回x的y次方的值。
print( pow(2,2) ) # 2的二次方
# 4
print( pow(2,-2) ) # 2的负二次方
# 0.25
print( pow(2,0.5) ) # 2的0.5次方
# 1.4142135623730951
format():一种格式化字符串的函数 ,基本语法是通过 {} 和 : 来代替以前的 % 。format 函数可以接受不限个参数,位置可以不按顺序。
print( "{}{}".format('a','1') )
# a1
print("{:2}*{:2}={:2}".format(4,5,4*5))
# 4* 5=20
print("{0:.2f}".format(3.14159265))
# 3.14
print("{0:.3f}".format(3.14159265))
# 3.142
print("{0:.4f}".format(3.14159265))
# 3.1416
len():返回对象(字符、列表、元组等)长度或元素个数
# len()方法返回对象(字符、列表、元组等)长度或元素个数。
print(len('1234')) # 字符串,返回字符长度4
print(len(['1234','asd',1])) # 列表,返回元素个数3
print(len((1,2,3,4,50))) # 元组,返回元素个数5
print(len(12)) # 注意:整数类型、浮点数类型不适用,否则报错
# TypeError: object of type 'int' has no len()
round() 方法返回浮点数x的四舍五入值。
print(round(4.3)) # 只有一个参数时,默认保留到整数
# 4
print(round(2.678,2)) # 保留2位小数
# 2.68
print(round(5/3,3)) # 运算表达式并保留3位小数
# 1.667
print(round(1.999999,3)) # 保留3位小数
# 2.0
sum()函数对参数进行求和计算。
print(sum([1,2,3])) # 6
print(sum([1,2,3],4)) # 列表计算总和后再加4,得到结果10
print(sum((1,2,3),4)) # 元组计算总和后再加4,得到结果10
进制转换函数:bin()、oct()、hex()。
print(bin(60)) #转换为二进制
# 0b111100
print(oct(60)) #转换为八进制
# 0o74
print(hex(60)) #转换为十六进制
# 0x3c
ASCII码转换函数:ord()、chr()
print(ord('A')) #65
print(chr(97)) #'a'
三、自定义函数
自定义函数的概念:用户自己编写的一段程序。
1、自定义函数的定义格式
【样例研习】
问题描述:输入两个数,输出它的最大公约数
def gcd(a,b):
for i in range(min(a,b),0,-1):
if a%i==0 and b%i==0:
return i
a=int(input())
b=int(input())
print(gcd(a,b))
【运行调试】
输入12 8,结果为4。
输入12 7,结果为None
;如需显示为1,则需将range(a,1,-1)
改为range(a,0,-1)
。
将在后续学习中讲解如何通过递归函数
来求解最大公约数。
小结:函数一般包括函数名、参数、返回值和函数体(语句块)四部分,其中函数名和函数体是必不可少的,参数和返回值根据需要选用。定义函数的基本格式如下
def 函数名(参数):
语句块
return 返回值
2、自定义函数的应用
(1)阶乘(factorial)
一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。
计算3!+7!+11!
def fac(n):
s=1
for i in range(1,n+1):
s*=i
return s
print(fac(3)+fac(7)+fac(11))
(2)孪生素数
输出1000以内所有的孪生素数对(差值为2)以及总对数。
def prime(n):
for i in range(2,int(n**0.5+1)):
if n%i==0:
return False
return True
s=0
for i in range(3,998,2):
if prime(i) and prime(i+2):
print(i,i+2)
s+=1
print(s)
(3)数字统计
统计在给定范围[L,R]的所有整数中,数字2出现的次数。
比如在给定范围[2,22],数字2在2中出现了1次,在12中出现了1次,在20中出现了一次,在21中出现了1次,在22中出现了两次,所以一共出现了6次
def tj(n):
s=0
while(n):
if n%10==2:
s+=1
n=n//10
return s
l=int(input())
r=int(input())
s=0
for i in range(l,r+1):
s+=tj(i)
print(s)
(4)火柴数字
火柴数字如下图:
现用6根火柴摆数字,请列出所有能摆出的自然数,要求每个数火柴全用上,不多不少。
【问题分析】
0~9每根所用的火柴棒数量:
数字 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
火柴棒 | 6 | 2 | 5 | 5 | 4 | 5 | 6 | 3 | 7 | 6 |
可以看出:1
最少,用了2根,8
最多,用了7根。不难分析出数字范围是[0,111]之间。
思考7根火柴棒的范围?[8,711] 18根火柴?
知道了数据范围
,且每个数需使用6根火柴的条件
明确,此时我们可以考虑使用穷举法
:将[0,111]的每个数的所使用的总火柴数统计,若为6则输出。
算法:通过循环列出 [0,111] 的每个数,再写一个内层循环判定每个数所使用的的火柴个数(与上面的数字统计类似),整体上是一个双层循环。外层从0取到111,内层把每个数的每一位所使用火柴数的和算出来,0~9十个数字的火柴数可以用列表来表示。参考程序如下:
f=[6,2,5,5,4,5,6,3,7,6] #0~9分别需要多少根火柴棒
print(0) #对0进行特殊处理,请思考为什么?
for i in range(112): #穷举范围
s=0 #统计总数目
ti=i #因i会在内层循环时发生改变,在此对i进行保存以便后续使用
while ti: #计算ti需要多少根火柴棒,ti非0才会执行循环,所以0不在计算范围
s+=f[ti%10] #个位所用的数量
ti=ti//10 #整除10,除去个位数
if s==6:
print(i)
代码复用
可以提高程序的效率,函数
和模块
是python中代码复用的常见方法,在此可以考虑将统计数字i所使用的的火柴棒数量
这一段代码封装为函数进行复用,既提高了效率也增强了代码的可读性。参考程序如下:
#统计数字所使用的的火柴棒数量
def tj(n):
f=[6,2,5,5,4,5,6,3,7,6]
if n==0:
return f[0]
else:
total=0
while n:
total+=f[n%10]
n=n//10
return total
for i in range(112):
if tj(i)==6:
print(i)
3、模块
任何人编写的代码都有可能帮到其他人,如何共享这些有价值的成果呢?常见的方法就是发布代码。请将“计算一个数字需要多少根火柴棒”的函数转换为模块,然后发布。
模块的作用:把常用的代码存成文件,让自己和别人都可以使用。
(1)发布代码
首先做好发布前的准备工作。创建文件夹D:\mymodule,其中包含mymodule.py和setup.py两个文件。
mymodule.py是一个模块文件,其内容就是tj函数。
def tj(n):
f=[6,2,5,5,4,5,6,3,7,6]
if n==0:
return f[0]
else:
total=0
while n:
total+=f[n%10]
n=n//10
return total
setup.py文件包含有关发布的元数据,代码如下:
from distutils.core import setup
setup(
name ='mymodule', #参数要与mymodule.py文件名相同
version ='1.0.0', #版本号
py_modules =['mymodule'], #参数一定要与mymodule.py文件名相同
author='ww', #作者
author_email='ww@mail.com', #作者邮箱
description ='计算一个数字需要多少根火柴棒', #代码功能描述
)
在DOS命令行中打开mymodule所在的目录,构建发布文件,命令如图1。请注意本机Python安装的位置,例子中Python安装在d:\python34文件夹中。
最后将发布安装到你的Python本地副本中,如图2。
安装完成后mymodule文件夹包含了如图3的文件。
(2)导入模块并使用
已经构建发布的模块必须先导入程序,然后才能使用。导入时使用语句“import mymodule”,调用模块内的函数时用“mymodule.tj()”来实现。
import mymodule #导入模块
print("使用6根火柴你可以拼出这些数字:")
for i in range(112):
if mymodule.tj(i)==6:
print(i,end=",")
四、递归函数
递归是计算科学领域中一种重要的计算思维模式。它既是一种抽象表达的手段,也是一种问题求解的重要方法。直接或间接地调用自身的方法称为递归,递归分为递推和回归。指一种通过重复将问题分解为同类的子问题,从而解决问题的方法。
在数学与计算机领域中,递归函数是指用函数自身来定义该函数的方法。如著名的斐波那契数列"1 1 2 3 5 8 13 …"
,可以递归定义为
F ( n ) = { 1 ( n = 1 或 n = 2 ) F ( n − 1 ) + F ( n − 2 ) ( n > 2 ) F(n)=\begin{cases}1\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space(n=1或n=2)\\ F(n-1)+F(n-2)\space\space\space\space(n>2) \end{cases} F(n)={1 (n=1或n=2)F(n−1)+F(n−2) (n>2)
递推关系是递归的重要组成,例如上式中的 F ( n ) = F ( n − 1 ) + F ( n − 2 ) F(n)=F(n-1)+F(n-2) F(n)=F(n−1)+F(n−2);而边界情况是递归的另一要素,例如上式中当 n 为 1 或 2 时的 F ( n ) = 1 F(n)=1 F(n)=1,它保证递归能在有限次的计算后得出结果,而不会产生无限循环的情况。
【样例研习】
以下为用递归算法求斐波那契数列的Python程序
def fibo(n):
if n==1 or n==2:
return 1
else:
return fibo(n-1)+fibo(n-2)
print(fibo(5))
本题的递推公式为
f
i
b
o
(
n
)
=
f
i
b
o
(
n
−
1
)
+
f
i
b
o
(
n
−
2
)
fibo(n)=fibo(n-1)+fibo(n-2)
fibo(n)=fibo(n−1)+fibo(n−2),边界条件为
f
i
b
o
(
1
o
r
2
)
=
1
fibo(1 \space or \space 2)=1
fibo(1 or 2)=1。
求解过程如下:
f i b o ( 5 ) = f i b o ( 4 ) + f i b o ( 3 ) = ( f i b o ( 3 ) + f i b o ( 2 ) ) + ( f i b o ( 2 ) + f i b o ( 1 ) ) = ( ( f i b o ( 2 ) + f i b o ( 1 ) ) + 1 ) + ( 1 + 1 ) = ( 1 + 1 ) + 1 ) + ( 1 + 1 ) = 5 fibo(5)\\ =fibo(4)+fibo(3)\\ =(fibo(3)+fibo(2))+(fibo(2)+fibo(1))\\ =((fibo(2)+fibo(1))+1)+(1+1)\\ =(1+1)+1)+(1+1)\\ =5 fibo(5)=fibo(4)+fibo(3)=(fibo(3)+fibo(2))+(fibo(2)+fibo(1))=((fibo(2)+fibo(1))+1)+(1+1)=(1+1)+1)+(1+1)=5
递归算法需确定的两个条件:
1、递推关系
2、边界条件(即递归退出的条件)
常用的递归代码框架:
def f(形式参数):
if 边界条件:
语句组
else:
递推公式
递归与迭代:
(1)递归与迭代算法都需要重复执行某些代码
(2)递归是重复调用函数自身,遇到满足终止条件时逐层返回;迭代是重复反馈过程,其目的是逼近所需目标或结果,通常使用计数器结束循环。
五、递归的应用
1、斐波那契数列:
1 1 2 3 5 8 13 21 34 55 89 ...
已知前两项为1,之后每一项等于前两项之和。
现输入n,请输出兔子数列的第n项。
2、用递归法求4!+5!+6!+7!的值。
F
(
n
)
=
{
1
(
n
=
0
)
n
∗
F
(
n
−
1
)
(
n
>
0
)
F(n)=\begin{cases}1\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space(n=0)\\ n*F(n-1)\space\space\space\space(n>0) \end{cases}
F(n)={1 (n=0)n∗F(n−1) (n>0)
以下为用递归算法求自然数n的阶乘的Python程序
def fac(n):
if n==0:
return 1
else:
return n*fac(n-1)
print(fac(4))
本题的递推公式为
f
a
c
(
n
)
=
f
a
c
(
n
−
1
)
∗
n
fac(n)=fac(n-1)*n
fac(n)=fac(n−1)∗n,边界条件为
f
a
c
(
0
)
=
1
fac(0)=1
fac(0)=1。
求解过程如下:
f a c ( 4 ) = 4 ∗ f a c ( 3 ) = 4 ∗ ( 3 ∗ f a c ( 2 ) ) = 4 ∗ ( 3 ∗ ( 2 ∗ f a c ( 1 ) ) ) = 4 ∗ ( 3 ∗ ( 2 ∗ ( 1 ∗ f a c ( 0 ) ) ) ) = 4 ∗ ( 3 ∗ ( 2 ∗ ( 1 ∗ 1 ) ) ) fac(4)\\ =4*fac(3)\\ =4*(3*fac(2))\\ =4*(3*(2*fac(1)))\\ =4*(3*(2*(1*fac(0))))\\ =4*(3*(2*(1*1))) fac(4)=4∗fac(3)=4∗(3∗fac(2))=4∗(3∗(2∗fac(1)))=4∗(3∗(2∗(1∗fac(0))))=4∗(3∗(2∗(1∗1)))
3、输入两个数,求其最大公约数。
根据上文中所讲的辗转相除法可得公式如下:
g
c
d
(
a
,
b
)
=
{
b
(
a
%
b
=
0
)
g
c
d
(
b
,
a
%
b
)
(
a
%
b
≠
0
)
gcd(a,b)= \begin{cases}b\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space(a\%b=0)\\ gcd(b,a\%b)\space\space\space\space(a\%b\neq 0) \end{cases}
gcd(a,b)={b (a%b=0)gcd(b,a%b) (a%b=0)
4、用递归法求1+2+3+…+100的值。
5、花果山上有一洞,小猴每次采取跳1阶或者跳3阶的办法从山下跳跃上台阶进洞,编程输入台阶数,输出有多少种不同的跳法。
学业水平测试题目
#拆解正整数
'''
(1) 从键盘输入一个正整数,拆解这个正整数,把组成这个数的各位数通过列表的方式显示出来。
(2) 不要更改源程序的功能和结构,删除程序中的①②③,填写正确的代码使程序完善。
'''
def qiugeweishu(num):
list=[]
while ①:
②
list.append(x)
③
return list
num=int(input("输入大于0的整数"))
weishu=qiugeweishu(num)
print(weishu)
#求各位数的平方和
def qpfh(num):
s=0
list=①
while num>0:
x=num%10
②
num=num//10
for i in list:
③
return s
num=int(input("输入大于0的整数"))
gwsh=qpfh(num)
print(gwsh)
#求最大值
def get_max(lst):
if not lst:
return None # 若为空列表,返回none值
max_value=lst[0]
for i in lst:
if i>max_value:
① # 确保max_value中的值是最大的
return ②
#下面主程序
number=[4,2,1,6,7,9]
max_number=③
print(max_number)
#阶乘
def factorial(n):
s=1
for i in range(2, n+1):
s=s*i
①
#下面主程序
abs=int(input('请输入需求解的阶乘数n:'))
total=②
print(total)
#Fibonacci
#请不要更改源程序的结构,删除原题里的①、②、③。填写正确的代码,完善程序。
def fib(n):
f2 = f1 = ①
for i in range(3, ②):
f1, f2 = f2, f1+f2
return ③
n = int(input('输入需要计算的月份数:'))
print('兔子总对数为:', fib(n))
input("运行完毕,请按回车键退出...")
#Fibonacci
#请不要更改源程序的结构,删除原题里的①、②、③。填写正确的代码,完善程序
def fib(n):
if n == 1 or n == 2:
return ①
else:
return fib(n-1)+fib(②)
n = int(input("输入需要计算的项数:"))
print("第", str(n) + "项的值为:", fib(③))
input("运行完毕,请按回车键退出...")
#递归求NK
# 请不要更改源程序的结构,删除原题里的①、②、③。填写正确的代码,完善程序。
def fun(n, k):
if(k == 0):
return 1
if(k == 1):
return ①
else:
return n*fun(n,②)
n = int(input("请输入n:"))
k = int(input("请输入k:"))
print(③)
#最大公约数
'''求两个数的最大公约数,可以用欧几里得算法(辗转相除法)。
其基于的定理是:两个数的最大公约数等于较小的那个数和这两个数相除的余数的最大公约数。
比如求m和n的最大公约数就要先用m和n取模(余数),
再用n和模取模……一直循环下去。直到模为0,那么最后一次的除数就是最大公约数。'''
# 请不要更改源程序的结构,删除原题里的①、②、③。填写正确的代码,完善程序。
def gcd(m, n):
r = ①
if ②:
return n
else:
return ③
m = int(input("请输入一个数:"))
n = int(input("请输入另一个数:"))
print(m, '和', n, '的最大公约数是:', gcd(m, n))
#有序序列
'''一个有序数列(含多个相同值),找出类似目标值的起始下标和末尾下标。
例如:数列[1,2,3,3,4,4,5,5,5,6,7,8,8]#输入5, 用二分法输出5的起始下标和末尾下标。'''
# 请不要更改源程序的结构,删除原题里的①、②。填写正确的代码,完善程序。
def searchRange(nums, target):
if len(nums) == 0:
return "not find"
elif target < nums[0] or target > nums[-1]:
return "not find"
else:
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r) // 2
if target > nums[mid]:
l = mid + 1
elif ①:
r = mid - 1
elif target == nums[mid]:
②
while l-1 >= 0 and nums[l-1] == target:
l -= 1
while r+1 <= len(nums)-1 and nums[r+1] == target:
r += 1
return [l,r]
return "not find"
nums = [1,2,3,3,4,4,5,5,5,6,7,8,8]
a = searchRange(nums,5)
print(a)
#质数对
#'找出100以内的质数对(若两个质数的差为2则称为质数对),并成对显示结果。
#'函数isp(m)判断参数m是否为质数。
#'请不要更改源程序结构,删除原题里的语句①、语句②、语句③ 。填写正确的代码,使程序完善
import math
def isp(m):
for i in range(2,int(math.sqrt(m))):
if ①==0 :
return False
return ②
p1=isp(3)
for i in range(5,101,2):
p2 = isp(i)
if p1 and p2: print(③,i)
p1 = p2
input("运行完毕,请按回车键退出...")
#小猴跳台阶
#请不要更改源程序结构,删除原题里的语句①、语句②,语句③。填写正确的代码,使程序完善。
import pdb
from tkinter import *
def s1(n):
if n == 1 or n == 2 :
return ①
else:
if n == 3:
return 2
else:
return s1(n-1)+s1(n-②)
def submit():
x = int(u.get())
lab3["text"]= str(s1(③))
root = Tk()
root.title("小猴跳台阶")
frame = Frame(root)
frame.pack(padx=8, pady=8, ipadx=4)
lab1 = Label(frame, text="输入台阶数")
lab1.grid(row=0, column=0, padx=5, pady=5, sticky=W)
u = StringVar()
ent1 = Entry(frame, textvariable=u)
ent1.grid(row=0, column=1, sticky='ew', columnspan=2)
lab2 = Label(frame, text="共有跳法:")
lab2.grid(row=1, column=1, padx=1, pady=1, sticky=W)
button = Button(frame, text="运 算", command=submit, default='active')
button.grid(row=2, column=1)
lab3 = Label(frame, text="",fg="red")
lab3.grid(row=1, column=2, sticky=W)
root.mainloop()
#多边形面积
#请不要更改源程序的结构,删除原题里的语句①、语句②。填写正确的代码,使程序完善
import math
def s(a,b,c):
p=(a+b+c)/2
mj=math.sqrt(①)
return mj
b1,b2,b3,b4,b5,b6,b7=3,2,3,4,3,4,5
print(s(②)+s(b2,b6,b7)+s(b3,b4,b7))
input("运行完毕,请按回车键退出...")
#上楼梯
#请不要更改源程序的结构,删除原题里的语句①、语句②。填写正确的代码,使程序完善
def f(n):
if n == 1 or n == 2:
return n
elif n>=3:
return ①
else:
return -1
n=int(input("请输入台阶数:"))
print(f(②))
input("运行完毕,请按回车键退出...")
#阶乘
#请不要更改源程序的结构,删除原题里的语句①、语句②。填写正确的代码,使程序完善
def factorial(n):
#求n!
s=1
for i in range(2,n+1):
s=①
return s
#调用factorial函数
total=0
for i in range(1,11):
total=total+②
print(total)
input("运行完毕,请按回车键退出...")
#一元多次方程
#请不要更改源程序结构,删除原题里的语句①、语句② ,语句③。填写正确的代码,使程序完善
def f(x):
f=x**5+x**4+x-10
return f
def f1(x):
f1=5*(x**4)+4*(x**3)+1
return f1
x=1
x1=2
print('迭代过程中的x值:')
while abs(①)>1e-10:
x1=x
y1=f(x)
y2=②
x=③
print(x)
print('近似解:',x)
#求组合数
def fac(n): #用递归的方法求n!
if n == __①__:
return 1
else:
return n*__②__
n=int(input("请输入正整数n的值:"))
m=int(input("请输入正整数m的值(m<=n):"))
c = fac(n)/(fac(m)*__③__)
print(c)