函数
name()
input() # 无参函数
print('Hello') # 有参函数
能力点1:定义和调用函数的能力
函数是可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性、代码的重用性和可维护性
内置函数,比如print()、input()
自己创建函数,用户自定义函数
示例 4.1 判断素数
- 输入一个正整数n
- 如果这个数小于2
- 不是素数
- 否则
- 遍历从2到n-1
- 判断其中有没有n的因子
- 如果存在因子
- 输出不是素数
- 终止循环
- 如果存在因子
- 判断其中有没有n的因子
- 如果遍历正常完成,即不存在因子
- 输出是素数 ```python n = int(input()) if n < 2: print(f’{n}不是素数’) # 0和1不是素数 else: for i in range(2, n): # 取2到n-1这间的每个数 if n % i == 0: # n能否被当前数整除,有整除则不是素数 print(f’{n}不是素数’) break # 判定n不是素数后不需要继续判定i后面的数字,结束循环,提高效率 else: # 未遇到break时执行else子句,此时一定是素数 print(f’{n}是素数’)
- 遍历从2到n-1
```python
# 函数的定义
def is_prime():
"""判断是否为素数,返回布尔值"""
n = int(input())
if n < 2: # 0和1不是素数
return False # 返回值
for i in range(2, n):
if n % i == 0:
return False # 返回值
else:
return True # 返回值
print(is_prime()) # 函数的调用
函数定义,调用和返回值
函数定义时应该加文档字符串,说明函数的作用,参数数量、类型、返回值数量和类型等信息。
# 函数的定义
def is_prime(n): # 括号里为传入的参数相当于赋值n = 100
"""接收一个整数为参数,判断是否为素数,返回布尔值"""
if n < 2: # 0和1不是素数
return False # 返回值
for i in range(2, n):
if n % i == 0:
return False # 返回值
else:
return True # 返回值
print(is_prime(100)) # 函数的调用
# 提高算法效率
def is_prime(n): # 括号里为传入的参数相当于赋值n = 100
"""接收一个整数为参数,判断是否为素数,返回布尔值"""
if n < 2: # 0和1不是素数
return False # 返回值
for i in range(2, int(n ** 0.5) + 1): # range参数必须为整数100-->10
if n % i == 0:
return False # 返回值
else: # else与for对齐,是循环语句的了句,与if无关
return True # 返回值
print(is_prime(100)) # 函数的调用
能力点2:为函数传递参数的能力
定义函数时有几个参数,调用函数时就需要传递几个参数
掌握位置传递参数
多参数,默认值参数
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
int(x, base=10)
def power(x, n=2): # 多个参数,默认值参数
"""接收一个数值型参数x,一个默认值参数n,n没有传入值时n=2
计算x的n次幂,返回计算结果
"""
result = 1
for i in range(n):
result = result * x # 注意乘的是x 不是i
return result # 返回计算结果
print(power(2, 10)) # 传入2个参数时,n= 10
print(power(2)) # 传入1个参数时,n用默认值
包裹传递参数
拆包就是将一个可迭代对象(range,列表,元组,字典,集合,字符串等)中的多个元素拆为多个对象
print(*'Hello') # H e l l o
print(*range(5)) # 0 1 2 3 4
args = ('Tom', 18, 'Male')
print(*args) # Tom 18 Male,可用此方法输出可迭代对象中的数据,空格分隔
# 字典用*解包得到的是键
dict = {'u_name': 'Tom', 'age': 18, 'gender': 'Male'}
func(*dict) # u_name age gender,
# 字典用**解包得到的是值
dict = {'u_name': 'Tom', 'age': 18, 'gender': 'Male'}
func(**dict) # Tom 18 Male,字典用**解包得到的是键
def func(u_name, age, gender):
print(u_name, age, gender)
args = ('Tom', 18, 'Male')
func(*args) # Tom 18 Male
能力点3:利用函数简化程序逻辑
def is_prime(n):
"""接收正整数n,判断是否为素数,返回布尔值"""
if n < 2:
return False # 0和1不是素数
for i in range(2, n): # 遍历(2, n-1)中的数
if n % i == 0: # 若在(2, n-1)中存在因子则不是素数
return False # 不是素数时返回False
else: # for语句遍历(2, n-1)中所有数,未发现因子存在时,才是素数
return True # 素数时返回True
if __name__ == '__main__':
num = int(input()) # 接收用户输入并转成整数
if is_prime(num): # 调用函数
print(f'{num}是素数')
else: # 调用函数
print(f'{num}不是素数')
示例4.2 哥德巴赫猜想
数学领域著名的“哥德巴赫猜想”的大致意思是:
任何一个大于2的偶数总能表示为两个素数之和。
例如:24=5+19,其中5和19都是素数。本实验的任务是设计一个程序,验证20亿以内的偶数都可以分解成两个素数之和。
输入一个大于2的正整数,当输入为偶数时,在一行中按照格式“N = p + q”输出N的素数分解,其中p 、 q均为素数且p ≤ q。
因为这样的分解可能不唯一(例如24还可以分解为7+17),要求必须输出所有解中p最小的解。当输入为奇数时,输出’Data error!’ 。
输入格式
输入一个不小于2的正整数
输出格式
当输入为偶数时,按照格式“N = p + q”输出N的素数分解;
当输入为奇数时,输出’Data error!’ 。
- 输入一个正整数n
- 设置一个标记变量
- 如果输入是偶数
- 从小到大遍历从1到n for p in range(1, n):
- 从小到大遍历从1到n for q in range(1,n):
- 如果 p 是素数,且q是素数,且p+q==n
- 输出n=p+q
- 改变标记变量值
- 结束内层循环
- 如果 p 是素数,且q是素数,且p+q==n
- 根据标记变量的值确定是否找到了解,如果找到了解
- 结束外层循环
- 从小到大遍历从1到n for q in range(1,n):
- 从小到大遍历从1到n for p in range(1, n):
如果输入不是偶数
- 输出’Data error!’
```python def is_prime(n): # 判断素数的函数 if n < 2:return False # 0和1不是素数
for i in range(2, n):
if n % i == 0: return False
else:
return True
用标记变量和2个break才能提前退出两重循环
若不定义素数函数,则需在3重循环
N = int(input()) # 接收用户输入并转成整数 flag = False if N % 2 == 0: for p in range(N): for q in range(N): if is_prime(p) and is_prime(q) and p + q == N: print(“{} = {} + {}”.format(N, p, N - p)) flag = True break if flag: break else: print(‘Data error!’)
```python
def is_prime(n):
"""接收正整数n,判断是否为素数,返回布尔值"""
if n < 2:
return False # 0和1不是素数
for i in range(2, n): # 遍历(2, n-1)中的数
if n % i == 0: # 若在(2, n-1)中存在因子则不是素数
return False # 不是素数时返回False
else: # for语句遍历(2, n-1)中所有数,未发现因子存在时,才是素数
return True # 素数时返回True
def goldbach(n):
"""接收正整数n,若为偶数,输出分解为素数加和的表达式
若不是偶数时,输出'Data error!'"""
if n % 2 == 0: # 若为偶数
for p in range(n//2 + 1): # 只遍历一半以前的数
if is_prime(p) and is_prime(n - p): # 若p为素数,且n-p也是素数
return f'{n} = {p} + {n-p}' # 返回表达式字符串,遇return结束循环
else: # 若为奇数
return 'Data error!' # 返回'Data error!'
if __name__ == '__main__':
num = int(input()) # 接收用户输入并转成整数
print(goldbach(num)) # 调用函数,输出函数返回值
能力点4 变量作用域
1. 全局变量
在模块层次(函数外)定义的变量
1.1 在函数内部可以访问(做为参数或出现在赋值号右侧)
def car(year, model):
"""参数为年份和型号,返回字符串"""
auto_brand = brand # brand是全局变量,函数内可以访问和使用
print(auto_brand) # 输出 宝马
return f'这是一辆{year}年生产,型号是{model}的{brand}牌汽车。'
brand = '宝马' # 全局变量
ls = input().split() # 根据空格切分输入字符串为列表
print(car(*ls)) # 调用函数,取列表中的全部数据做参数
2021 525i
宝马
这是一辆2021年生产,型号是525i的宝马牌汽车。
1.2 在函数内部给全局变量赋值会创建新的同名局部变量,影响函数外部全局变量的值
def car(year, model):
"""参数为年份和型号,返回字符串"""
brand = '劳斯莱斯' # 创建新的局部变量名brand,不影响函数外部的值
print(brand) # 输出 劳斯莱斯
return f'这是一辆{year}年生产,型号是{model}的{brand}牌汽车。'
brand = '宝马' # 全局变量
ls = input().split() # 根据空格切分输入字符串为列表
print(car(*ls)) # 调用函数,取列表中的全部数据做参数
print(brand) # 宝马
2021 525i
劳斯莱斯
这是一辆2021年生产,型号是525i的劳斯莱斯牌汽车。
宝马
1.3 函数内修改全局变量的值可以在变量名前加关键字 global
def car(year, model):
"""参数为年份和型号,返回字符串"""
global brand
brand = '劳斯莱斯' # 全局变量名brand绑定到新对象上,相当于修改了值
print(brand) # 输出 劳斯莱斯
return f'这是一辆{year}年生产,型号是{model}的{brand}牌汽车。'
brand = '宝马' # 全局变量
ls = input().split() # 根据空格切分输入字符串为列表
print(car(*ls)) # 调用函数,取列表中的全部数据做参数
print(brand) # 劳斯莱斯
2021 525i
劳斯莱斯
这是一辆2021年生产,型号是525i的劳斯莱斯牌汽车。
劳斯莱斯
1.4 在函数内部可用原地操作方法修改可变类型全局变量的值
def car(year, model):
"""参数为年份和型号,返回字符串"""
brand_ls.append('劳斯莱斯') # 全局变量brand_ls原地增加新元素
print(brand_ls) # 输出 ['宝马', '劳斯莱斯']
return f'这是一辆{year}年生产,型号是{model}的{brand_ls[1]}牌汽车。'
brand_ls = ['宝马'] # 可变数据类型全局变量
ls = input().split() # 根据空格切分输入字符串为列表
print(car(*ls)) # 调用函数,取列表中的全部数据做参数
print(brand_ls) # ['宝马', '劳斯莱斯']
2019 745li
[‘宝马’, ‘劳斯莱斯’]
这是一辆2019年生产,型号是745li的劳斯莱斯牌汽车。
[‘宝马’, ‘劳斯莱斯’]
2. 局部变量
在函数内部定义的变量,用完就销毁
在函数外部无法访问
def car(year, model):
"""参数为年份和型号,返回字符串"""
brand = '劳斯莱斯' # 局部变量名brand,只有函数内部可访问
print(brand) # 输出 劳斯莱斯
return f'这是一辆{year}年生产,型号是{model}的{brand}牌汽车。'
ls = input().split() # 根据空格切分输入字符串为列表
print(car(*ls)) # 调用函数,取列表中的全部数据做参数
print(brand) # NameError: name 'brand' is not defined
2019 745li
劳斯莱斯
这是一辆2019年生产,型号是745li的劳斯莱斯牌汽车。
print(brand) # 劳斯莱斯
NameError: name ‘brand’ is not defined
算法1:递归
示例4.3 阶乘
def fact(n):
if n == 0: # 必须有一个终止条件
return 1 # 此时返回值确定值
else:
return n * fact(n - 1) # 当前数n的阶乘等于n与前一个数阶乘的乘积
num = int(input())
print(fact(num))
示例4.4 猴子吃桃
描述
猴子第1天摘了一堆桃子吃了一半又多一个,第2天吃了剩下的一半又多一个,…,第10天早上时发现只有1个桃子了。问第1天摘了多少?
第10天余1个桃子
第9天余4个桃子,2 (peach(10) + 1)
第8天余10个桃子,2 (peach(9) + 1)
第7天余22个桃子,2 (peach(8) + 1)
第6天余46个桃子,2 (peach(7) + 1)
第5天余94个桃子,2 (peach(6) + 1)
第4天余190个桃子,2 (peach(5) + 1)
第3天余382个桃子,2 (peach(4) + 1)
第2天余766个桃子,2 (peach(3) + 1)
第1天余1534个桃子,2 * (peach(2) + 1)
- 定义函数
- 如果是第10天
- 返回值只剩1个桃子
- 否则返回桃子数量为后面一天桃子数量加1乘2
- 如果是第10天
- 输出第一天数量
def peach(day):
if day == 10: # 必须有一个终止条件
return 1 # 此时返回值确定值
else:
return 2 * (peach(day + 1) + 1) # 后面一天桃子数量加1乘2,调用函数本身,规模变小
print(peach(1))
递归有深度限制
递归有层次限制,1000左右,操作系统限制4000左右
循环没有次数限制,建议优先用循环
def peach(day):
if day == 1000:
return 1
else:
return 2 * (peach(day + 1) + 1) # 后面一天桃子数量加1乘2
print(peach(1))
if day == 1000:<br />RecursionError: maximum recursion depth exceeded in comparison
import sys
sys.setrecursionlimit(3900) # 用sys中的方法改变递归栈深度
def peach(day):
if day == 3494:
return 1
else:
return 2 * (peach(day + 1) + 1) # 后面一天桃子数量加1乘2
print(peach(1))
94383506707880119754754048645789755724090203656771185206515156748743982508217352707360950352103421591392896498830209795074697702627207367107553591516785958153633365493734160057486717116758000333344743150268694082271796533226044514673879152706390649090930408892486471407502577264049586455950418875351028786460850838033103255904072590971746322449835583505006495257190229742056919947782449887434632228091520901431007070898179709128949362654286389236116545365469172749138337714491412347814682558371778807380649351116805460001779164439400065150382816635537204755944969133012431907069121740022804757349675866507489546453676099734220985844431391170771641784263483115325656146276118096654473925891319406869669292301512471448775025920358512979563961763836158573622695029158118334029288843123682428012267452044399619835290721915520457633768409034208684591253260984575484121420242955370959467532290571598837821147509192959971781615483174639379997621428287965319618190362323300011587566803587183592336332476372644502477398385031616817081718676789759536001110245374
import sys
sys.setrecursionlimit(3900)
def peach(day):
if day == 3495:
return 1
else:
return 2 * (peach(day + 1) + 1) # 后面一天桃子数量加1乘2
print(peach(1))
Process finished with exit code -1073741571 (0xC00000FD)
循环方法无层次限制
num = 1
for i in range(9, 0, -1):
num = (num + 1) * 2
print(f'第{i}天有{num}个桃子')
第9天有4个桃子
第8天有10个桃子
第7天有22个桃子
第6天有46个桃子
第5天有94个桃子
第4天有190个桃子
第3天有382个桃子
第2天有766个桃子
第1天有1534个桃子
num = 1
for i in range(999, 0, -1):
num = (num + 1) * 2
print(f'第{i}天有{num}个桃子')
第1天有16072629107794009814226375735900027158421072175583004111656255825555265766874041837397975682235437871913920093763297202377807179285384710653976866362047862205901851662236346478131611907593556712816931273229569712475372911901098151338748315919115594371856794716529813251490644747478936580255808502104062个桃子
能力点5:匿名函数lambda
def f(x):
return len(x)
ls = ['58', '01', '9', '920']
print(sorted(ls)) # ['01', '58', '9', '920']
print(sorted(ls, key=int)) # ['01', '9', '58', '920']
print(sorted(ls, key=f)) # ['9', '58', '01', '920']
print(sorted(ls, key=lambda x: len(x))) # ['9', '58', '01', '920']
print(sorted(ls, key=lambda x: int(x))) # ['01', '9', '58', '920']
能力点6:为函数加文档测试
# 利用文档测试可以检验函数的输出是否与预期相符
# >>>后面空一个字符加函数的调用,后面一行写期望的输出值
def is_prime(n):
"""接收正整数n,判断是否为素数,返回布尔值.
>>> is_prime(1)
False
>>> is_prime(2)
True
>>> is_prime(3)
True
>>> is_prime(13)
True
>>> is_prime(25)
False
"""
if n < 2:
return False # 0和1不是素数
for i in range(2, n): # 遍历(2, n-1)中的数
if n % i == 0: # 若在(2, n-1)中存在因子则不是素数
return False # 不是素数时返回False
else: # for语句遍历(2, n-1)中所有数,未发现因子存在时,才是素数
return True # 素数时返回True
if __name__ == '__main__':
num = int(input()) # 接收用户输入并转成整数
if is_prime(num): # 调用函数
print(f'{num}是素数')
else: # 调用函数
print(f'{num}不是素数')
# 利用文档测试可以检验函数的输出是否与预期相符
# >>>后面空一个字符加函数的调用,后面一行写期望的输出值
import math
def area_of_circle(radius):
"""接收一个表示圆半径的浮点数为参数,利用Math库中的圆周率计算面积.
返回表示面积的浮点数.
>>> area_of_circle(5)
78.54
>>> area_of_circle(3)
28.27
"""
area = math.pi * radius * radius # 计算面积
return round(area, 2) # 返回面积,保留小数点后2位
if __name__ == '__main__':
r = float(input()) # 输入转浮点数
print(area_of_circle(r)) # 调用函数,传递半径,计算面积
def is_leap(year):
"""接收一个整数表示年份,判断是否为闰年,返回布尔值.
>>> is_leap(1995)
False
>>> is_leap(1900)
False
>>> is_leap(1996)
True
>>> is_leap(2000)
True
"""
if year % 4 == 0 and year % 100 != 0 or year % 400 == 0:
return True
else:
return False
if __name__ == '__main__':
year = int(input())
print(is_leap(year))