8.1函数入门
什么是函数函数就是完成特定功能的一段代码
为什么需要函数复用代码、隐藏实现细节、提高可维护性、提高可读性
创建函数
def 函数名([参数列表]):
函数体
[return返回值]
函数调用本质上就是在执行函数体
def show():
print("大家好")
print("我叫张三")
print("今年24岁")
show()
print("结束")
8.2 函数的返回值
1.可选项
2.需要给调用者返回数据,使用return+数据
3.可返回多个数据,以元组返回–python特有的
4.如果不需要返回数据,可以return语句
5.函数体中可以根据条件判断,通过return提前结束函数
#返回一个值
def show():
return '我叫张三'
s=show()
print(s)
#返回两个值
def show():
return 6,'hello'
s=show()
print(s)#输出(6,'hello')
s,t=show()
print(s,t)#输出6,'hello'
8.3 函数的参数
当完成特定功能,需要调用者提供数据的时候,可以给函数定义参数
函数定义的时候,参数叫形式参数,简称形参列表:
函数调用的时候,参数叫实际参数,简称实参列表,实参个数和形参个数一致
# 计算两个数的和
def getSum(num1,num2): #num1,num2 形参列表
return num1+num2
s=getSum(13,5) #13,5 实参列表
print(s)
参数传递
在函数体中,形参重新赋值,不会影响到实参
在函数体中,修改可变对象中的元素,会影响到实参
# 在函数体中,形参重新赋值,不会影响到实参
def f1(num):
num=13
a=10
f1(a)
print(a) #10
print('-----------')
def swap(m,n):
temp=m
m=n
n=temp
x=14
y=45
swap(x,y)
print(x,y) # 14,45
print('-----------')
s='hello'
s.replace('h','H')
print(s) #hello
print('-----------')
def f2(lst):
lst=[1,2,3]
lst2=[4,5,6]
f2(lst2)
print(lst2) #[4,5,6]
print('-----------')
s = {-3,89,23,-1}
for i in s:
if i<0:
i=0
print(s)
print('------参数是可变对象,在函数体中,修改可变对象,会影响到实参------')
def f2(lst):
lst[0]=99
lst2=[4,5,6]
f2(lst2)
print(lst2)
print('-----------')
d = {'a':12,'b':20}
for key,value in d.items():
if value<18:
# value=18
d[key]=18
print(d)
参数类型
位置实参 实参按照顺序依次传递给形参
def f1(name,age):
print(name,age)
a='Mike'
b=12
f1(a,b)
# 使用可变容器统一传递参数,需要使用*,依次取出可变序列中的元素按照位置实参传递
lst =['Tom',16]
f1(*lst)
关键字实参按照形参名传递,与顺序无关
可以与位置参数混用,但位置实参在前,关键字实参在后
def f1(name,age):
print(name,age)
f1(name='Jack',age=18)
f1(age=18,name='Jack')
#使用**,可以依次将字典中的元素按照关键字实参传递
d = {'name':'Monkey','age':6}
f1(**d)
默认值形参
#默认值形参,可以不传递,如果传递,以实参优先
#默认参数必须要指向不可变对象
def f1(a,b=0):
print(a,b)
f1(12)#因为b有默认值,可以不传递
f1(12,6)
print('',end='')# print()函数的end参数也是有默认值的,默认为\n
可变个数的形参
#可变个数的位置形参,前面加*,形参会以元组的方式接收
print('--------------')
print('hello','world','')
def f2(*nums):
print(nums)
f2(1,2,3,4)
f2()
#可变个数的关键字形参,前面加**,形参会以字典的方式接收
print('----------')
def f3(**kwargs):
print(kwargs)
f3(name='Monkey',age=6,phone='9999999998')
d={'name':'Monkey','age':6,'phone':'9999999998'}
f3(**d)
# 参数的顺序:位置参数--默认值参数--关键字参数
# 一般一个函数中,可变个数的位置形参只有一个,可变个数的关键字形参也只有1个
8.4 递归
递归是一种算法思想,就是函数自己调用自己
把一个大的复杂的问题,化简成一个跟他相似但规模更小的问题
递归的好处:想起来简单,编码也简单
递归的缺点:内存占用大,效率低
递归的编码
1、递归公式-- f(n)=f(n-1)+n
2、临界条件 f(1)=1
# 1+2+3+4+5
# f(num)---功能计算1+。。。+num和
'''
f(5) = f(4) +5 return 1+2+3+4+5
f(4) = f(3) +4 return 1+2+3+4
f(3) = f(2) +3 return 1+2+3
f(2) = f(1) +2 return 1+2
f(1) = 1 return 1
分递和归两个过程。
'''
def fsum(num):
if num==1:
return 1
else:
sum=fsum(num-1)+num
return sum
print(fsum(5))
斐波那契数列、兔子数列
从第三项开始,每一项都是前面两项数字的和,如 1,1,2,3,5,8,13…
#输出前100项的斐波那契数列项
#第n项的数字是多少 --fibo(n)
'''
fibo(1)=1
fibo(2)=1
fibo(n)=fibo(n-1)+fibo(n-2)
'''
def fibo(n):
if n==1 or n==2:
return 1
else:
return fibo(n-1)+fibo(n-2)
for i in range(1,50):
print(fibo(i))
'''
使用循环来解决,效率明显提高
num1=1
num2=1
num3=num1+num2
num1=num2
num2=num3
num3=num1+num2
'''
def fibo2(n):
num1 = 1
num2 = 1
num3 = num1 + num2
print(num1)
print(num2)
print(num3)
i=4
while i <= n:
num1 = num2
num2 = num3
num3 = num1 + num2
print(num3)
i+=1
fibo2(50)
汉诺塔
'''
汉诺塔
有三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。
需求:把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
'''
def havo(start,middle,end,n):
if n==1:
print(start+'--》'+end)
else:
# 1、前n-1个 从start,经end,移动到middle
havo(start,end,middle,n-1)
# 2、把第n个盘子,从start,移动end
print(start + '--》' + end)
# 3、前n-1个,从middle,经start,移动end
havo(middle, start, end, n-1)
havo('a','b','c',64)
8.5 全局变量和局部变量
# 全局变量 定义在函数外部的变量
a=1
# 局部变量:定义在某些代码块中的变量
def f():
m=12
# 在函数内部,只能读,不能改全局变量。
def f2():
# global a #使用global修饰,则可以修改全局变量,但是不提倡
# a+=1 #函数体内不能修改全局变量
a='hello' # 局部变量可以和全局变量重名,但是局部变量的优先级更高
print(a)
异常处理
try…except…else…finally
try:
# 可能出现异常的代码
num1 = int(input('请输入一个整数')) # ValueError: invalid literal for int()
with base 10: 's'
num2 = int(input('请输入一个整数'))
result = num1 / num2 # ZeroDivisionError: division by zero
print(result)
except ValueError:
# 出现异常的处理方法
print('应该输入数字')
except ZeroDivisionError:
# 出现异常的处理方法
print('除数不能为0')
else:
# try块中正常执行结束,就执行else,如果有异常,则不执行
print('else子------')
finally:
# 不管是否出现异常,都会执行的代码--释放资源,收场
print('finally---------')
print('程序结束')
# return语句也不能阻挡finally块代码的执行
def f():
try:
print('try')
a=1/0
return 1
except:
print('execpt---')
return -1
finally:
print('finally---')
带参函数练习
# 1、定义函数,完成两个数加减乘除的计算
# 提示:def cal(num1,num2,opr):
# return result
def cal(num1,num2,opr):
if opr=='+':
result=num1+num2
elif opr=='-':
result=num1-num2
elif opr=='*':
result=num1*num2
elif opr=='/':
result=num1/num2
return result
# 2、定义函数,计算矩形的周长和面积
#s代表面积,p代表周长,l代表长,w代表宽
def sp(l,w):
p=(l+w)*2
s=l*w
return s,p
print(sp(12,10))
# 3、定义函数,从文件名中获取后缀,如e:/project/demo/homework.py获取的后缀.py
def getzip(string):
num=string.rindex('.')
b=string[num:]
return b
print(getzip('e:/project/demo/homework.py'))
# 4、定义函数,从请求地址中提取出域名
# 如http://www.qqzone.com?qqid=270808123&pwd=111111,域名为www.qqzone.com
def geturl(url):
num1=url.find('//')
num2=url.find('?')
if num2 == -1:
b = url[num1 + 2:]
else:
b = url[num1+ 2:num2]
return b
print(geturl('http://www.qqzone.com?qqid=270808123&pwd=111111'))
# 5、定义函数,判断邮箱格式是否正确,校验规则:邮箱中必须包含@符号
def cheak(email):
print( '@' in email)
cheak('sssdsz.eaa')
# 6、定义函数,判断一个字符串中是否既有数字又有字母
# def judge(a):
# if a.isalnum and a.isalpha:
# print('ok')
# judge(21)
# 7、定义函数,统计一个列表中各个字符出现的次数
def get_count(lst):
d = {}
for i in lst:
v = d.get(i)
if v==None:
#如果没有,就添加,值为1
d[i]=1
else:
#如果有,则取出值+1再更新,
d[i]=v+1
# 8、定义函数,判断一个列表中是否有4个连续相同的数
def ftrue(list, num=0,i=0):
r=list[0] # 前一个元素
for i in range(len(list)): # 当前正遍历的元素
if r==list[i]:
num=num+1
elif r!=list[i]:
print(F"{r}连续出现的次数为{num}")
num=1
r = list[i]
if i==len(list)-1:
print(F"{r}出现的次数为{num}")
list1=[2,3,3,3,3,6,8,9,40]
ftrue(list1)
# 9、定义函数,对整数列表数据按奇偶排序,偶数在前,奇数在后
# 示例:
# 输入:[3,1,2,4]
# 输出:[2,4,3,1]
# 输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。
def sort(lst):
left = 0
right = len(lst)-1
while True:
# 1 从左往右找奇数的位置,找不到left+1,直到找到为止
while lst[left]%2==0:
left+=1
# 2 从右往左找偶数的位置,找不到right-1,直到找到为止
while lst[right]%2==1:
right-=1
if left<right:
temp = lst[left]
lst[left]=lst[right]
lst[right]=temp
else:
break
lst = [24,13,1,9,35,46,2,4]
sort(lst)
print(lst)
# 10、输出前100个回文素数,且每10个换行
# 提示:定义函数,判断一个数是否是回文数
# 定义函数,判断一个数是否是素数
def isHuiwen(num):
s = str(num)
s2 = s[-1::-1]
return s==s2
def isSu(num):
for i in range(2,num//2+1):
if num%i==0:
return False
return True
def isHuiwenAndSu(num):
return isHuiwen(num) and isSu(num)
def printHuiWenAndSu():
n=2
count = 0
while True:
if isHuiwenAndSu(n):
print(n,end=',')
count+=1
if count==100:
break
elif count%10==0:
print()
n+=1
print(isHuiwen(12321))
print(isSu(4))
# print(isHuiwenAndSu())
printHuiWenAndSu()
无参函数练习
# 定义函数,实现菜单的级联效果(从一级菜单可以跳转二级菜单,从二级菜单可以返回一级菜单)
#
# 1、一级菜单
# *****欢迎进入银行系统*********
# 1、注册
# 2、登录
# 3、退出
# *******************************
# 请选择:
# 2、二级菜单
# *******************************
# 1、查询余额
# 2、存款
# 3、取款
# *******************************
# 请选择(输入0返回上一级):
def menu1():
print(' *****欢迎进入银行系统*********\n1、注册\n2、登录\n3、退出\n*******************************')
choice=int(input())
if choice==1:
print('注册')
menu1()
elif choice==2:
print('登录')
menu2()
elif choice==3:
print('退出')
def menu2():
print('*******************************\n1、查询余额\n2、存款\n3、取款\n*******************************')
choice=int(input())
if choice==0:
return menu1()
elif choice==1:
print('查询余额')
menu2()
elif choice==2:
print('存款')
menu2()
elif choice==3:
print('取款')
menu2()
menu1()