主要解决的问题:
将那些具有独立性功能的,且重复的代码进行封装
这一段代码,专门用于处理某一个问题
比如素数问题:
a = 10
b = 110
c = 129087
# 哨兵:监控状态变化
flag = True # 默认是素数
for n in range(2, a // 2 + 1):
if a % n == 0:
flag = False
break
if flag:
print("YES")
else:
print("No")
# 哨兵:监控状态变化
flag = True # 默认是素数
for n in range(2, b // 2 + 1):
if b % n == 0:
flag = False
break
if flag:
print("YES")
else:
print("No")
# 哨兵:监控状态变化
flag = True # 默认是素数
for n in range(2, c // 2 + 1):
if c % n == 0:
flag = False
break
if flag:
print("YES")
else:
print("No")
到底什么是函数:
就是一个具有固定功能的一段代码,根据不同输入的参数,进行同样的计算,得到了不同的结果
python当中 函数的语法格式:
def 函数名(参数列表):
函数体,具体的执行内容
return 返回值
# 如果函数不需要返回 则可以不写return
# return 它仅仅表示结束当前函数 如果有返回值则写上 没返回值可以不写return 默认返回None
# 函数必须先定义 再调用(除了面向对象在类中定义函数时)
素数问题进行函数化:
# 素数问题
def isSushu(num):
for n in range(2, num // 2 + 1):
if num % n == 0:
return False
return True
# TypeError: isSushu() missing 1 required positional argument: 'num'
# NameError: name 'isSushu' is not defined
# isSushu()
def isSushuNoReturn(num):
for n in range(2, num // 2 + 1):
if num % n == 0:
print(False)
return
print(True)
return # 其实可以不写 但是存在 (隐藏的)
# print(isSushu(11))
print(isSushuNoReturn(11))
关于函数局部变量的一些问题:
n = 10
def test01(n):
#局部变量n 用于接受外部变量的数据
n = 20 #n是test01内部创建的一个变量
test01(n)
print(n)
arr = [1,2,3]
def test02(arr):
#局部变量arr 用于接受外部变量的数据
arr[0] = 666 #arr是test02内部创建的一个变量
test02(arr)
print(arr)
n = 100
def test03():
n = 200 #函数内部创建的变量
m = 300 #函数内部创建的变量
test03()
print(n)
print(m) #NameError: name 'm' is not defined
在函数的外面,并不能调用函数内部创建的变量(局部变量)
一定要区分,在函数内部
操作的变量是局部还是全局的
=是创建还是修改
n = 100
def test04(n): # n 是以局部变量的形式创建的 然后在接收全局n的100
n = 200 # 修改
m = 300 # 创建
test04(n)
print(n)
print(m)
如何修改外部变量,用 global 关键字去指定
n = 100
m = 300
def test05():
n = 666
print(n)
global n, m # 事先指定哪些变量是全局的
n = 200
m = 400
print(n)
# SyntaxError: name 'n' is used prior to global declaration
# 在函数内部 局部变量和全局变量 不要重名
test05()
print(n)
print(m)
n = 100
m = 300
def test06():
global n
n = 200 # 已经被声明为全局
m = 400 # 局部变量
test06()
print(n, m)
def test07(arr): # 局部变量 函数被调用时 指向[1,2,3]
arr = [2, 3, 4] # 被修改 指向[2,3,4]
arr = [1, 2, 3]
test07(arr)
print(arr)
python主函数的问题
函数还能将代码进行模块化,解耦,方便阅读、维护、设计
# 程序的入口 看成主函数
if __name__ == "__main__":
print("Hello World")
关于函数的具体执行的流程
函数的运行 是基于栈内存的
每一个函数看作是栈内存元素
哪个函数在栈顶 那么它就优先执行 直到调用别的函数 当前函数暂停执行
函数但凡被调用 则加载到栈内存中 成为新的栈顶
函数执行完毕(遇到return)则弹栈 新的栈顶继续执行
递归
# 递归
def show():
arr = [0] * 1000000000000000 # MemoryError 堆内存溢出
print("show") # RecursionError: maximum recursion depth exceeded 栈内存溢出
show()
def main():
show()
if __name__ == "__main__":
main()
所谓的递归 其实就是函数自身调用自身
栈内存溢出 栈主要存函数的 函数存不下了(主要还是因为递归)
堆内存溢出 堆主要存对象的 对象存不下了(一直在创建新的数据对象)
递归的应用
递归如果设计不当,容易导致占内存溢出
所以之后在写递归的时候,需要注意啥?注意递归什么时候结束!
递归,它可以将一个大型复杂的问题,进行逐层的化解,化为若干个较小的问题,同时这些较小的 问题也可继续进行化解为若干个更小的问题,直到该问题不能被化解为止(终止递归)->原子问题 是可以直接被求解的
所以,将所有原子问题的解,进行合并,就得到了原问题的解
原子问题之间的求解,不能相互作用,互不影响!
每一层问题的求解方式,都是一致的!
上述的内容,就是【分治算法】
但凡是迭代的问题,都可以被递归写,但反过来就不一定了
同样的一个问题,用迭代写的代码较多,用递归写的代码较少
递归可以用少量的代码来解决较大的问题
人用迭代,神用递归
(1)计算1~100之间的求和问题
# (1)计算1~100之间的求和问题
"""
f(100) = 1+2+3+4+....+99+100
f(99) = 1+2+3+4+...+98+99
f(n) = f(n - 1) + n
f(100) = f(99) + 100
f(99) = f(98) + 99 1+2+3+...+98 + 99
....
f(4) = f(3) + 4 1+2+3 + 4
f(3) = f(2) + 3 1+2 + 3
f(2) = f(1) + 2 1 + 2
f(1) = 1 # 递归的边界条件
f(100)->f(1) 递归的前进段
f(1) = 1 递归的边界条件
f(1)->f(100) 递归的返回段
1, n = 1
f(n)
f(n-1) + n, n > 1
"""
def nSum(n):
if n == 1:
return 1
return nSum( n - 1 ) + n
(2)斐波那契数列
#(2)斐波那契数列
"""
1 1 2 3 5 8 13 21 34 55 89 ...
f(n) = f(n-1) + f(n-2)
f(5)
f(4) + f(3)
f(3) + f(2) f(2) + f(1)
f(2) + f(1)
1, n ∈[1,2]
f(n)
f(n-1) + f(n-1), n > 2
"""
def fibo(n):
if n == 1 or n == 2:
return 1
return fibo(n - 1) + fibo(n - 2)
(3)二分查找
def binarySearch(arr , L , R , key):
if L > R :
return -1
M = (L + R) // 2
if arr[M] == key:
return M
elif arr[M] < key:
return binarySearch(arr , M+1 , R , key)
elsr:
return binarySearch(arr , L , M-1 , key)
def main():
print(nsum(100))
#print(fibo(40))
arr = [1,2,3,4,5,6,7,8,9,10]
key = 11
print(binarySearch(arr , 0 , len(arr) - 1 , key))
if__name__ == "__main__"
main()
(4) 快速排序(三路快速排序)
import random
def quicksort(arr , L , R):
if L > R:
return
lt = L
gt = R + 1
idx = random.randint(0 , R - L) + L
arr[L], arr[idx] = arr[idx], arr[L]
V = arr[L]
i = L + 1
while i < gt:
if arr[i] < V:
arr[lt + 1], arr[i] = arr[i], arr[lt + 1]
lt += 1
i += 1
elif arr[i] > V:
gt -= 1
arr[gt], arr[i] = arr[i], arr[gt]
else:
i += 1
arr[L], arr[lt] = arr[lt], arr[L]
# 递归处理左边
quickSort(arr, L, lt - 1)
# 递归处理右边
quickSort(arr, gt, R)
def main():
global count
arr = [0] * 50
for i in range(len(arr)):
arr[i] = random.randint(0,1000)
quickSort(arr, 0, len(arr) - 1)
print(arr)
if __name__ == "__main__":
main()
(5) 汉诺塔问题
"""
前3个 X -> Z
前2个 X -> Y
前1个 X -> Z
第2个 X -> Y
前1个 Z -> Y
第3个 X -> Z
前2个 Y -> Z
前1个 Y -> X
第2个 Y -> Z
前1个 X -> Z
"""
def hanoi(n , begin , mid , end):
if n == 1:
print(begin + " -> " + end)
else:
hanoi(n-1 , begin , end , mid)
print(begin + " -> " + end)
hanoi(n-1 , mid , begin ,end)
def main():
X = "X"
Y = "Y"
Z = "Z"
hanoi(3 , X , Y ,Z)
if __name__ == "__main__" :
main()
(6) 全排列
#全排列问题
"""
"ABC"
ABC
ACB
BAC
BCA
CAB
CBA
"""
result = [] # set集合适用于去重复的操作
def permutation(arr , left , right):
if left == right:
s = ""
for c in arr:
s += c
if s not in result:
result.append(s)
else:
for i in range(left , right + 1):
arr[i] , arr[left] = arr[left] , arr[i]
permutation(arr , left + 1 , right)
arr[i] , arr[left] = arr[left] , arr[i]
def main():
s = input()
arr = list(s)
permutation(arr , 0 , len(arr) - 1)
print(result)
if __name__ == "__main__" :
main()
关于二维数组的补充
"""
二维列表
所谓的二维列表 本质上还是一个一维列表
只不过该一维列表中 的每一个元素 又是另一个一维列表而已
"""
arr = [1,2,3]
matrix = [[1,2,3],[4,5,6],[7,8,9]]
print(matrix[0])
print(matrix[0][1])
#锯齿二维数组
matrix = [[1,2,3],
[1,2,3,4,5],
[7,8]]
#二维数组的遍历
for i in range(len(matrix)):
for j in range(len(matrix[i])):
print(matrix[i][j])
#如何去创建一个指定宽高/行列 但是没有元素的空二维数组
row = 5
col = 8
matrix = [0] * row
print(matrix)
for i in range(row):
matrix[i] = [0] * col
print(matrix)
for i in range(len(matrix)):
for j in range(len(matrix[i])):
print(matrix[i][j],end = " ")
print()
利用二维数组,来去实现一个五子棋游戏 棋盘 15×15
#用于区分黑白棋 奇偶性 统计棋子的个数
player = 0
#棋盘设置
def creatBoard(size):
board = [None] * size
for i in range(size):
board[i] = ["+"] * size
return board
def printBoard(board):
for i in range(len(board)):
for j in range(len(board[i])):
print(board[i][j], end = " ")
print()
#下棋的逻辑
def playChess(chess , board):
global player
row = int(input(">>>请输入行:")) - 1
col = int(input(">>>请输入列:")) - 1
if board[row][col] == "+" :
board[row][col] = chess
else:
print(">>>此处已存在棋子,请重新下棋")
player -= 1
printBoard(board)
#判断游戏是否结束(五子连珠 或者 和棋)
def isGameOver(board):
global player
for row in range(len(board)):
for col in range(len(board[row])):
#如果有“+”,表示有空格出现,则没有五子连珠或和棋
if board[row][col] == "+" :
continue
#向右
if col < 11:
if board[row][col] == board[row][col + 1] == board[row][col + 2] == board[row][col + 3] == board[row][col + 4]:
return True
#向下
if row < 11:
if board[row][col] == board[row + 1][col] == board[row + 2][col] == board[row + 3][col] == board[row + 4][col]:
return True
#向右下
if row < 11 and col < 11:
if board[row][col] == board[row + 1][col + 1] == board[row + 2][col + 2] == board[row + 3][col + 3] == board[row + 4][col + 4]:
return True
#向右上
if row > 3 and col < 11:
if board[row][col] == board[row - 1][col + 1] == board[row - 2][col + 2] == board[row - 3][col + 3] == board[row - 4][col + 4]:
return True
if player == 15 * 15:
return True
return False
def main():
global player
#创建棋盘
board = creatBoard(15)
#打印棋盘
printBoard(board)
#游戏逻辑
while not isGameOver(board):
if player % 2 == 0:
print(">>>请黑方下棋")
playChess("●", board)
else:
print(">>>请白方下棋")
playChess("○", board)
player += 1
if player % 2 == 1:
print(">>黑棋胜!")
else:
print(">>白棋胜!")
if __name__ == "__main__":
main()
N皇后问题(递归)
"""
N皇后问题(递归)
"""
N = 4 #几皇后问题
#构建二维数组
arr = [0] * N
for i in range(N) :
arr[i] = [0] * N
count = 0
def isDangerous(row , col): #判断是否危险(是否可以成为皇后) True为不可以 Flase为可以
#正上
r = row - 1
while r >= 0:
if arr[r][col] == 1: #如果上面有皇后
return True #直接结束循环
r -= 1 #继续向上一行判断
#左上
r = row - 1
c = col - 1
while r >= 0 and c >=0:
if arr[r][c] == 1:
return True
r -= 1
c -= 1
#右上
r = row - 1
c = col - 1
while r >= 0 and c < N :
if arr[r][c] == 1:
return True
r -= 1
c += 1
return False #以上全都没有返回False则为不危险
def nQueen(row): #row从第一行开始向下遍历到 N 行
global count
if row == N: #如果row从上到下遍历完 N 层 , 表示一种结果产生
count += 1
print(f"第{count}种解:") #打印这是第几种解法
#打印这个矩阵
for i in range(len(arr)):
for j in range(len(arr[i])):
print(arr[i][j] , end = " ")
print()
else:
for col in range(N):
if not isDangerous(row , col): #如果不危险 则这个格子可以是皇后
arr[row][col] = 1 #第row行col个格子标记为这行的皇后
nQueen(row + 1) #row向下移一行继续判断
arr[row][col] = 0 #当前行走完了没有到下一行得清零
def main():
nQueen(0)
if __name__ == "__main__":
main()
函数编程练习(55,56,68,72)
Demo55 测试密码
s = input()
flag = True #哨兵:假设所设置密码合格
if len(s) < 8: #判断密码长度
print("密码至少8个字符")
flag = False
dx = 0 #是否为大写
sz = 0 #是否有数字
for i in s :
if i.isupper(): #判断是否为大写
dx += 1
if i.isupper(): #判断是否有数字
sz += 1
if dx < 2: #如果大写小于2个
print("密码至少两大写")
flag = False
if sz < 2: #如果数字小于2个
print("密码至少两数字")
flag = False
for j in s:
if i.isupper() and i. isupper(): #大写和数字是否同时有
flag = True
if flag == True:
print("通过")
else:
print("错误")
Demo56 回文素数
def is_zhishu(num):
for i in range(2, num // 2 + 1):
if num % i == 0:
return False
return True
def is_huiwenshu(num):
if str(num) == str(num)[::-1]:
return True
count = 0
num = 2
while count < 100:
if is_zhishu(num) and is_huiwenshu(num):
print("%5d" % num, end=" ")
count += 1
if count % 10 == 0:
print()
num += 1
Demo68 豆机器
import random
def createPath(length):
path = ""
for i in range(length):
if random.randint(0 , 1) == 1: #[0 , 1]
path = path + "R"
else:
path += "L"
return path
def countR(path):
count = 0
for C in path:
if C == "R":
count += 1
return count
def main():
arr = input().split(" ")
balls = int(arr[0]) #球的个数
slots = int(arr[1]) #槽子的个数
box = [0] * slots #槽子数组
for i in range(balls):
path = createPath(slots - 1)
print(path)
index = countR(path)
box[index] += 1
print(box)
if __name__ == "__main__" :
main()
Demo72 猜单词游戏
import random
#根据明文单词和状态 构建密文
def createPasswd(word , state):
passwd = ""
for i in range(len(word)):
if state[i]:
passwd += "#"
else:
passwd += word[i]
return passwd
#游戏是否结束 True结束
def isGameOver(state):
return True not in state
#修改状态 True修改成功 False未修改(已存在)
def isChangeState(state):
return True not in state
def isChangeState(state , word , ch):
for i in range(len(word)):
if word[i] == ch:
if state[i]:
state[i] = False
else:
return False
return True
def main():
#单词组
words = ["banana" , "orange" , "computer" , "refrigerator" , "program"]
while True:
#明文单词
word = words[random.randint(0 , len(words) - 1)]
#单词状态
state = [True] * len(word)
#制作密文
passwd = createPasswd(word , state)
#错误次数
missed = 0
while not isGameOver(state):
#输入一个字母
ch = input("Enter a letter in word" + passwd + ">")
#判断在不在
#如果在 判断是否已修改
if ch in word:
if isChangeState(state , word , ch):
passwd = createPasswd(word , state)
else:
print(ch + "is not in the word")
#如果不在统计次数
else:
missed += 1
print(ch + " is not in the word")
#提示单词 错误次数
print(f"The word is {word}. You missed {missed} time")
#询问是否继续
choice = input("是否继续? y/n >")
if choice == "n":
break
if __name__ == "__main__" :
main()