5 函数和代码复用

5.1 函数的定义与使用

  • 函数是一段代码的表示

  • def <函数名>(<函数参数>):

    <函数代码>

  • 函数的调用:调用时要给出实际参数

  • 可选参数:可选参数某些参数提供默认值,可选参数必须放在必选参数后面

    1
    2
    3
    4
    5
    6
    def fact(n,m=1):
    s = 1
    for i in range(1,n+1)
    s*=i
    s = s/m
    return s
  • 可变参数的传递:函数定义时可以设计可变数量参数,即不确定参数总数量

    1
    2
    3
    4
    5
    6
    7
    def fact(n,*b)
    s = 1
    for i in range(1,n+1)
    s *= i
    for item in b
    s *= b
    return s
  • 位置对应,名字对应

    1
    fact(m=5,n=10)
  • 返回值:返回多个数据,元组类型:return s//m, n, m (元组类型)

  • 在函数中使用全局变量:保留字global

  • 局部变量为组合数据类型且未创建,等同于全局变量

    1
    2
    3
    4
    5
    6
    ls = ['F','f']
    def func(a):
    ls.append(a)
    return
    func("c")
    print(ls)
  • lambda 函数:是一种匿名函数,返回函数名

    • <函数名> = lambda <参数>:<表达式>

      1
      2
      3
      f = lambda x,y:x+y
      f(10,15)
      f = lambda: "lambda function"

5.2 实例7:七段数码管绘制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#SevenDigitsDrawV1.py
import turtle
def drawLine(draw): #绘制单段数码管
turtle.pendown() if draw else turtle.penup()
turtle.fd(40)
turtle.right(90)
def drawDigit(digit): #根据数字绘制七段数码管
drawLine(True) if digit in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,6,8] else drawLine(False)
turtle.left(90)
drawLine(True) if digit in [0,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,2,3,4,7,8,9] else drawLine(False)
turtle.left(180)
turtle.penup()
turtle.fd(20)
def drawDate(date): #获得要输出的数字
for i in date:
drawDigit(eval(i)) #通过eval()函数将数字变为整数
def main():
turtle.setup(800, 350, 200, 200)
turtle.penup()
turtle.fd(-300)
turtle.pensize(5)
drawDate('20181010')
turtle.hideturtle()
turtle.done()
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#SevenDigitsDrawV2.py
import turtle, time
def drawGap(): #绘制数码管间隔
turtle.penup()
turtle.fd(5)
def drawLine(draw): #绘制单段数码管
drawGap()
turtle.pendown() if draw else turtle.penup()
turtle.fd(40)
drawGap()
turtle.right(90)
def drawDigit(d): #根据数字绘制七段数码管
drawLine(True) if d in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if d in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if d in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if d in [0,2,6,8] else drawLine(False)
turtle.left(90)
drawLine(True) if d in [0,4,5,6,8,9] else drawLine(False)
drawLine(True) if d in [0,2,3,5,6,7,8,9] else drawLine(False)
drawLine(True) if d in [0,1,2,3,4,7,8,9] else drawLine(False)
turtle.left(180)
turtle.penup()
turtle.fd(20)
def drawDate(date):
turtle.pencolor("red")
for i in date:
if i == '-':
turtle.write('年',font=("Arial", 18, "normal"))
turtle.pencolor("green")
turtle.fd(40)
elif i == '=':
turtle.write('月',font=("Arial", 18, "normal"))
turtle.pencolor("blue")
turtle.fd(40)
elif i == '+':
turtle.write('日',font=("Arial", 18, "normal"))
else:
drawDigit(eval(i))
def main():
turtle.setup(800, 350, 200, 200)
turtle.penup()
turtle.fd(-350)
turtle.pensize(5)
# drawDate('2018-10=10+')
drawDate(time.strftime('%Y-%m=%d+',time.gmtime()))
turtle.hideturtle()
turtle.done()
main()

5.3 代码复用与函数递归

  • 代码复用与模块化设计:
    • 函数和对象是代码复用的两种主要形式
    • 紧耦合:两个部分之间交流很多,无法独立存在
    • 松耦合:两个部分交流较少,可以独立存在
  • 函数递归:函数定义中调用函数自身的方式
1
2
3
4
5
def fact(n):
if n == 0:
return 1
else:
return n*fact(n-1)
  • 字符串反转
1
2
3
4
5
def rvs(s):
if s=='':
return s
else:
return rvs(s[1:])+s[0]
  • 汉诺塔:
1
2
3
4
5
6
7
8
9
10
def hanoi(n,src,dst,mid):
global count
if n == 1:
print("{}:{}->{}".format(1,src,dst))
count += 1
else:
hanoi(n-1,src,mid,dst)
print("{}:{}->{}".format(n,src,dst))
count += 1
hanoi(n-1,mid,dst,src)

5.4 模块4:PyInstaller库的使用

  • Windows 命令行 pyinstaller -F <filename.py>
  • 常用参数:

woIdNF.png

5.5 实例8:科赫雪花小包裹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#KochDrawV2.py
import turtle
def koch(size, n):
if n == 0:
turtle.fd(size)
else:
for angle in [0, 60, -120, 60]:
turtle.left(angle)
koch(size/3, n-1)
def main():
turtle.setup(600,600)
turtle.penup()
turtle.goto(-200, 100)
turtle.pendown()
turtle.pensize(2)
level = 5 # 3阶科赫雪花,阶数
koch(400,level)
turtle.right(120)
koch(400,level)
turtle.right(120)
koch(400,level)
turtle.hideturtle()
main()
turtle.done()

5.Practice

  • 任意累积:计算任意个输入数字的乘积
1
2
3
4
5
6
7
def cmul(*a):
s = 1
for item in a:
s *= item
return s

print(eval("cmul({})".format(input())))
  • 斐波那契数列:
1
2
3
4
5
6
7
8
def fbi(n):
if n in [1,2]:
return 1
else:
return fbi(n-1)+fbi(n-2)

n = eval(input())
print(fbi(n))
  • 汉诺塔实践:每个步骤一行,每行参考格式如下:[STEP 10] A->C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
steps = 0
def hanoi(src, des, mid, n):
global steps
if n == 1:
steps += 1
print("[STEP{:>4}] {}->{}".format(steps, src, des))

else:
hanoi(src,mid,des,n-1)
steps += 1
print("[STEP{:>4}] {}->{}".format(steps, src, des))
hanoi(mid,des,src,n-1)

N = eval(input())
hanoi("A", "C", "B", N)
  • 连续质数计算:输入n,输出n后面的5个质数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def prime(m):
if m < 2:
return False
else:
end = int(pow(m, 0.5) + 1)
for i in range(2, end):
if m%i == 0:
return False
else:
return True

n = eval(input())
n = (int(n) + 1) if (n > int(n)) else int(n)
count = 5
while count > 0:
if prime(n):
if count > 1:
print(n, end=',')
else:
print(n)
count -= 1
n += 1