Python程序语言设计 4

目录

5 函数和代码复用

5.1 函数的定义和使用

5.1.1 函数的理解和定义

5.1.2 函数的使用及调用过程

5.1.3 函数的参数传递

5.1.4 函数的返回值

5.1.5 局部变量和全局变量

5.1.6 lambda函数

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

5.2.1 问题分析

5.2.2 实例编写

2.4.2 补充:

5.3 代码复用与函数递归

5.3.1 代码复用与模块化设计

5.3.2 函数递归

5.4 模块4:pyinstaller库的使用

5.4.1 pyinstaller库的介绍

5.4.2 pyinstaller库的使用

5.5 实例八:科赫雪花

5.5.1 问题分析

5.5.2实例编写


5 函数和代码复用

5.1 函数的定义和使用

5.1.1 函数的理解和定义

作用:降低编程难度 进行代码复用

函数的定义

def 函数名(0个或多个参数)

函数体

return 返回值

例如:计算阶乘n!

def fact(n):

sum=1

for i in range(1,n+1):

sum *= i

return sum

5.1.2 函数的使用及调用过程

调用时要给实际参数去替换定义时的形式(占位)参数

5.1.3 函数的参数传递

函数可以有参数也可以没有参数,但括号必须有

可选参数传递

函数定义时可以为某些参数设定默认值,构成可选参数,要放在后面;放前面的非可选参数是指调用时必须要有的参数

def 函数名(非可选参数,可选参数):

函数体

return 返回值

例如:计算阶乘整除 n!//m

def fact(n,m=1): #如果没给参数m,默认m=1

sum=1

for i in range(1,n+1):

sum *= i

return sum//m

可变参数传递

函数定义时可以设计可变数量的参数,即不确定参数的总量

变量名前带上星号*

def 函数名(参数,*可变参数)

函数体

return 返回值

例如:

def fact(n,*b):
    sum=1
    for i in range(1,n+1):
        sum *= i
    for item in b:
        sum *= item
    return sum

调用fact(10,3),计算过程:10!*3=1088640

调用fact(10,3,5),计算过程:10!*3*5=54432000

参数传递的两种方式

按位置传递 按名称传递

例如:

def fact(n,m=1)

按位置:fact(10,5)

按名称:fact(m=5,n=10)

5.1.4 函数的返回值

返回0或多个结果

不管要不要传递返回值,都可以加上return

例如:

def fact(n,m=1):

sum=1

for i in range(1,n+1):

sum *= i

return sum//m,n,m

调用fact(10,5) 结果为:(725760, 10, 5) ------元组类型

或者a,b,c=fact(10,5) 用abc接收结果

5.1.5 局部变量和全局变量

局部变量:函数内部使用

全局变量:函数外部试用

例如:

n,m=10,100
def fact(n):
    m=1
    for i in range(1,n+1):
        m=m*i
    return m
print(fact(n),m)

结果:

3628800 100

使用规则:

规则1:基本数据类型,无论是否重名,局部变量和全局变量是不同变量

局部变量是函数内部的占位符,与全局变量可能重名但不同

函数运算结束后,局部变量被释放(这个局部变量不再存在)

可以使用global保留字在函数内部使用全局变量

例如:

n,m=10,100

def fact(n):

global m #声明这个m是函数外部的全局变量m

for i in range(1,n+1):

m=m*i

return m

print(fact(n),m)

结果:

362880000 362880000

规则2:局部变量为组合数据类型且未在函数内部真实创建,等同于全局变量

例如:

p=["x","y","z"]  #使用[]真实创建了全局变量列表p
def func(a):
    p.append(a) #此处p是列表类型,未真实创建,等同于全局变量
    return 
func("o")
print(p)

结果:

['x', 'y', 'z', 'o']

对比:

p=["x","y","z"]  
def func(a):
    p=[] #创建了p,就是局部变量
    p.append(a) 
    return 
func("o")
print(p)

结果:

['x', 'y', 'z']

5.1.6 lambda函数

主要用作一些特定函数或方法的参数,有些函数的参数就是一个函数,这种情况用lambda函数。一般情况下还是用def

用法:函数名=lambda 参数:表达式

等价于:

def 函数名(参数):

函数体

return 返回值

例如:

>>>f = lambda x,y : x+y
>>>f(5,6)
11
>>>g=lambda:"函数哦"    #没有参数
>>>print(g())
函数哦

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

5.2.1 问题分析

七段数码管也就是数字8的电子显示

利用turtle绘图体系绘制电子时间显示屏

思路:

绘制一个数码管

获得一串数字,绘制对应数码管

获得当前系统时间,绘制对应数码管

5.2.2 实例编写

import turtle as t
import time
#绘制数码管间隔
def gap():
    t.penup()
    t.fd(5)
#绘制一段线
def line(a):
    gap()
    if a:
        t.pendown()
    else:
        t.penup()
    t.fd(50)
    gap()
    t.right(90)
#绘制数字数码管
def digit(b):
    #判断各段有哪些数字要显示
    #第1条
    if b in [2,3,4,5,6,7,8,9]:
        line(True)
    else:
        line(False)
    #简写:line(True) if d in [2,3,4,5,6,7,8,9] else line(False)
    #第2条
    if b in [0,1,3,4,5,6,7,8,9]:
        line(True)
    else:
        line(False)
    #第3条
    if b in [0,2,3,5,6,8,9]:
        line(True)
    else:
        line(False)
    #第4条
    if b in [0,2,6,8]:
        line(True)
    else:
        line(False)
    #回到起点,此时不需要右转,所以左转回来
    t.left(90)
    #第5条
    if b in [0,4,5,6,8,9]:
        line(True)
    else:
        line(False)
    #第6条
    if b in [0,2,3,5,6,7,8,9]:
        line(True)
    else:
        line(False)
    #第7条
    if b in [0,1,2,3,4,7,8,9]:
        line(True)
    else:
        line(False)
    t.left(180)
    t.penup()
    t.fd(20)
#获取数字
def date(d):
    t.pencolor("red")
    for i in d:
        if i == "年":
            t.write("年",font=("Arial",36,"normal"))
            t.pencolor("green")
            t.fd(60)
        elif i == "月":
            t.write("月",font=("Arial",36,"normal"))
            t.pencolor("blue")
            t.fd(60)
        elif i == "日":
            t.write("日",font=("Arial",36,"normal"))
        else:
            digit(eval(i))
def main():
    t.bgcolor("black")
    t.hideturtle()
    t.tracer(False)
    #t.speed(10)
    t.setup(1200,350,200,200)
    t.penup()
    t.fd(-300)
    t.pensize(5)
    date(time.strftime("%Y年%m月%d日",time.gmtime()))
    t.done()
main()

5.3 代码复用与函数递归

5.3.1 代码复用与模块化设计

用函数和对象两种主要形式进行代码复用

函数:将代码命名,在代码层面建立了初步抽象,将代码变成功能组

对象:通过属性和方法,将一组变量或一组函数进一步抽象

模块化设计:通过函数或对象封装程序,将程序划分为模块及模块间的表达;关注主程序、子程序和子程序间的关系

紧耦合:两部分交流多,无法独立存在

松耦合:两部分交流少,可以独立存在

函数的参数和返回值就是函数与其他代码之间的交流通道,通道越少约清晰,函数复用的可能性越高,所以模块内部(函数内)尽量是紧耦合,模块外部(函数外部)之间松耦合,方便调用

5.3.2 函数递归

经典例子:阶乘

 

递归定义

调用函数自身,两个特性:

链条:计算过程间的对应关系

基例:存在一个或多个不需要递归(递归的最末端)

所以递归最重要的是找到链条和基例

递归的实现

函数+分支语句

递归本身是一个函数 函数内部用分支语句对基例和链条分别编写对应代码

def fact(n):
    if n==0:
        return 1
    else:
        return n*fact(n-1)

例:字符串反转

def res(s):
    if s=="":
        return s
    else:
        return res(s[1:])+s[0] #妙!把第一个字符放到最后面

例:斐波那契数列

def f(n):
    if n==1 or n==2:
        return 1
    else:
        return f(n-1)+f(n-2)

例:汉诺塔问题的解法

问题描述:n个大小不一的圈套在柱子上,通过一个辅助柱子移到另一个柱子,要求移动后也是上小下大

基例:只有一个圈,直接移

链条:先把上面的n-1个圆盘从起始搬到辅助柱子,剩下一个最大的直接搬到目标柱子,再把辅助柱子的圆盘搬到目标柱子

count=0 #记录移动次数
def hanoi(n,left,mid,right): #分别为圈数、起始柱子、辅助柱子、目标柱子
    global count #用global全局变量,否则每次调用都被清0
    if n==1:
        print("{}: {}->{}".format(1,left,right))
        count=count+1
    else:
        #先把上面的n-1个圆盘从起始搬到辅助柱子,剩下一个最大的直接搬到目标柱子
        hanoi(n-1,left,mid,right)
        print("{}: {}->{}".format(n,left,right))
        count=count+1
        #再把辅助柱子的圆盘搬到目标柱子,至于怎么搬,递归就可以实现
        hanoi(n-1,mid,left,right)
#调用
hanoi(4,"A","B","C")
print("COUNT=",count)

结果:

1: A->C
2: A->C
1: B->C
3: A->C
1: B->C
2: B->C
1: A->C
4: A->C
1: B->C
2: B->C
1: A->C
3: B->C
1: A->C
2: A->C
1: B->C
COUNT= 15

5.4 模块4:pyinstaller库的使用

5.4.1 pyinstaller库的介绍

pyinstaller库是第三方库,需要额外安装,官方网站:PyInstaller Manual — PyInstaller 5.3 documentation

将 .py 源代码转换成无需源代码的可执行文件---打包为 .exe

打包过程使用pyinstaller,打包完成后就不需要了

通过pyinstaller将Python源代码转换为Windows、Mac OS、Linus可执行的文件

安装第三方库---pip工具

win+R 打开cmd命令

pip install +库名  安装第三方库

pip list                   查看已安装库

pip uninstall         卸载已安装库

pip show              显示已安装库信息

方法1:右击IDLE打开所在文件夹---打开scripts文件夹---shift+右击---选择打开powershell窗口---输入pip install+库名

方法2:win+R 打开cmd命令---输入:pip install pyinstaller

方法3:自定义安装,去官网找安装包或路径安装,下载后自动安装

方法4:下载文件安装,在 www.lfd.uci.edu/~gohlke/pythonlibs可以找到所有第三方库的文件

5.4.2 pyinstaller库的使用

方法1:win+R 打开cmd命令

方法2:在.py 的文件夹空白处 shift+右击---选择打开powershell窗口

-F 打包:pyinstaller -F 文件名.py

留下dist里的.exe就可以,build和spec(可能还有_pycache_)可以删掉

-h 查看帮助:

--clean 清理临时文件:pyinstaller -F --clean 文件名.py

-i 修改图标:pyinstaller -i 图标文件名.ico -F 文件名.py

iconfont-阿里巴巴矢量图标库 下载ico图片

制作ico图标 | 在线ico图标转换工具 方便制作favicon.ico - 比特虫 - Bitbug.net 转换为.ico

修改后在dist里面图标可能没变,但是移动到其他位置后就变了

5.5 实例八:科赫雪花

5.5.1 问题分析

分形几何

一种迭代关系的几何图形,广泛存在于自然界,简单说就是整体和局部的结构相似

科赫雪花曲线

5.5.2实例编写

用Python绘制科赫雪花曲线

一条线段三等分,然后中间凸起两条(等边三角形),以此类推,不断迭代

基例:0阶(线段)

链条:每个线段凸起

import turtle as t
def koch(size,n):  #size表示长度,n表示绘制阶数
    if n==0:
        t.fd(size)
    else:
        for angle in [0,60,-120,60]:
            t.left(angle)
            koch(size/3,n-1)
def main():
    t.setup(800,400)
    t.speed(10)
    t.pu()
    t.goto(-300,-50)
    t.pd()
    t.pensize(2)
    koch(600,3)
    t.hideturtle()


main()

绘制结果:

如何形成雪花?以三角形为基础,两次转弯

import turtle as t
def koch(size,n):  #size表示长度,n表示绘制阶数
    if n==0:
        t.fd(size)
    else:
        for angle in [0,60,-120,60]:
            t.left(angle)
            koch(size/3,n-1)
def main():
    t.setup(1200,800)
    #t.tracer(False) 
    t.speed(10)
    t.pu()
    t.goto(-300,200)
    t.pd()
    t.pensize(2)
    level=3
    koch(600,level)
    t.right(120) #转两次弯变成三角形
    koch(600,level)
    t.right(120)
    koch(600,level)
    t.hideturtle()


main()

如果尝试改变阶数和基础图形? 改参数,注意找好角度关系

import turtle as t
def koch(size,n):  #size表示长度,n表示绘制阶数
    if n==0:
        t.fd(size)
    else:
        for angle in [0,60,-120,60]:
            t.left(angle)
            koch(size/3,n-1)


level=eval(input("请输入雪花阶数:"))
r=eval(input("基础形状为正?边形:"))
angle=(r-2)*180/r


t.setup(1200,800)
#t.tracer(False)
t.speed(0)
t.pu()
t.goto(-300,200)
t.pd()
t.pensize(2)
koch(400,level)
for i in range(r-1):
    t.right(180-angle)
    koch(400,level)

例如:

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值