......................................................................................................................................................................................

函数的代码和复用

......................................................................................................................................................................................

函数的定义与使用

函数的理解和定义

函数的定义

函数是一段代码的表示

  • 函数是一段具有特定功能的、可重用的语句组
  • 函数是一种功能的抽象,一般函数表达特定功能
  • 两个作用:降低编程难度 和 代码复用
def <函数名>(<参数(0个或多个)>) :
<函数体>
return <返回值>
  • 函数定义时,所指定的参数是一种占位符
  • 函数定义后,如果不经过调用,不会被执行
  • 函数定义时,参数是输入、函数体是处理、结果是输出 (IPO)

函数的使用及调用过程

函数的调用

调用是运行函数代码的方式

def fact(n) :   函数的定义
s = 1
for i in range(1, n+1):
s *= i
return s

fact(10) 函数的调用

  • 调用时要给出实际参数
  • 实际参数替换定义中的参数
  • 函数调用后得到返回值

函数的参数传递

参数个数

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

def <函数名>() :
<函数体>
return <返回值>

例:

def fact() :
print("我也是函数")

可选参数传递

函数定义时可以为某些参数指定默认值,构成可选参数

def <函数名>(<非可选参数>, <可选参数>) :
<函数体>
return <返回值>

例:

def fact(n, m=1) :
s = 1
for i in range(1, n+1):
s *= i
return s//m
>>> fact(10)
3628800
>>> fact(10,5)
725760

可变参数传递

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

def <函数名>(<参数>, *b ) :
<函数体>
return <返回值>

例:

def fact(n, *b) :
s = 1
for i in range(1, n+1):
s *= i
for item in b:
s *= item
return s
>>> fact(10,3)
10886400
>>> fact(10,3,5,8)
435456000

参数传递的两种方式

函数调用时,参数可以按照位置或名称方式传递

def fact(n, m=1) :
s = 1
for i in range(1, n+1):
s *= i
return s//m >>> fact( 10,5 ) 位置传递
725760
>>> fact( m=5,n=10 ) 名称传递
725760

函数的返回值

函数可以返回0个或多个结果

  • return保留字用来传递返回值
  • 函数可以有返回值,也可以没有,可以有return,也可以没有
  • return可以传递0个返回值,也可以传递任意多个返回值

局部变量和全局变量

n, s = 10, 100   -n和s是全局变量
def fact(n) :
s = 1 -fact()函数中的n和s是局部变量
for i in range(1, n+1):
s *= i
return s
print(fact(n), s) -n和s是全局变量 运行结果
>>>
3628800 100

规则1: 局部变量和全局变量是不同变量

  • 局部变量是函数内部的占位符,与全局变量可能重名但不同
  • 函数运算结束后,局部变量被释放
  • 可以使用global保留字在函数内部使用全局变量
n, s = 10, 100
def fact(n) : -fact()函数中s是局部变量,与全局变量s不同
s = 1
for i in range(1, n+1):
s *= i
return s -此处局部变量s是3628800
print(fact(n), s) -此处全局变量s是100 运行结果
>>>
3628800 100
n, s = 10, 100
def fact(n) :
global s -fact()函数中使用global保留字声明,此处s是全局变量s
for i in range(1, n+1):
s *= i
return s -此处s指全局变量s
print(fact(n), s) -此处全局变量s被函数修改 运行结果
>>>
362880000 362880000

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

ls = ["F", "f"]  -通过使用[]真实创建了一个全局变量列表ls
def func(a) :
ls.append(a) -此处ls是列表类型,未真实创建,则等同于全局变量
return
func("C") -全局变量ls被修改
print(ls) 运行结果
>>>
['F', 'f', 'C']
ls = ["F", "f"]  -通过使用[]真实创建了一个全局变量列表ls
def func(a) :
ls = [] -此处ls是列表类型,真实创建,ls是局部变量
ls.append(a)
return
func("C") -局部变量ls被修改
print(ls) 运行结果
>>>
['F', 'f']
  • 基本数据类型,无论是否重名,局部变量与全局变量不同
  • 可以通过global保留字在函数内部声明全局变量
  • 组合数据类型,如果局部变量未真实创建,则是全局变量

lambda函数

lambda函数返回函数名作为结果

  • lambda函数是一种匿名函数,即没有名字的函数
  • 使用lambda保留字定义,函数名是返回结果
  • lambda函数用于定义简单的、能够在一行内表示的函数

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

等价于

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

<函数体>

return <返回值>

例:

>>> f = lambda x, y : x + y
>>> f(10, 15)
25
>>> f = lambda : "lambda函数"
>>> print(f())
lambda函数

谨慎使用lambda函数

  • lambda函数主要用作一些特定函数或方法的参数
  • lambda函数有一些固定使用方式,建议逐步掌握
  • 一般情况,建议使用def定义的普通函数

实例7: 七段数码管绘制

基本思路

  • 步骤1:绘制单个数字对应的数码管
  • 步骤2:获得一串数字,绘制对应的数码管
  • 步骤3:获得当前系统时间,绘制对应的数码管
    #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()

绘制漂亮的七段数码管

    #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()

理解方法思维

  • 模块化思维:确定模块接口,封装功能
  • 规则化思维:抽象过程为规则,计算机自动执行
  • 化繁为简:将大功能变为小功能组合,分而治之

代码复用与函数递归

代码复用与模块化设计

代码复用

把代码当成资源进行抽象

  • 代码资源化:程序代码是一种用来表达计算的"资源"
  • 代码抽象化:使用函数等方法对代码赋予更高级别的定义
  • 代码复用:同一份代码在需要时可以被重复使用

函数 和 对象 是代码复用的两种主要形式

函数:将代码命名

在代码层面建立了初步抽象

对象:属性和方法

<a>.<b> 和 <a>.<b>()

在函数之上再次组织进行抽象

模块化设计

分而治之

  • 通过函数或对象封装将程序划分为模块及模块间的表达
  • 具体包括:主程序、子程序和子程序间关系
  • 分而治之:一种分而治之、分层抽象、体系化的设计思想

紧耦合 松耦合

  • 紧耦合:两个部分之间交流很多,无法独立存在
  • 松耦合:两个部分之间交流较少,可以独立存在
  • 模块内部紧耦合、模块之间松耦合

函数递归的理解

递归的定义

函数定义中调用函数自身的方式

两个关键特征

  • 链条:计算过程存在递归链条
  • 基例:存在一个或多个不需要再次递归的基例

递归是数学归纳法思维的编程体现

函数递归的调用过程

递归的实现

函数 + 分支语句

  • 递归本身是一个函数,需要函数定义方式描述
  • 函数内部,采用分支语句对输入参数进行判断
  • 基例和链条,分别编写对应代码

函数递归实例解析

字符串反转

将字符串s反转后输出

>>> s[::-1]

或者递归

def rvs(s):
if s == " " :
return s
else :
return rvs(s[1:])+s[0]

斐波那契数列

一个经典数列

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

汉诺塔

count = 0
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)

模块4: PyInstaller库的使用

PyInstaller库基本介绍##

PyInstaller库概述

将.py源代码转换成无需源代码的可执行文件

PyInstaller库是第三方库

PyInstaller库的安装

(cmd命令行) pip install pyinstaller

PyInstaller库使用说明

简单的使用

(cmd命令行) pyinstaller -F <文件名.py>

PyInstaller库常用参数

参数 描述
-h 查看帮助
--clean 清理打包过程中的临时文件
-D, --onedir 默认值,生成dist文件夹
-F, --onefile 在dist文件夹中只生成独立的打包文件
-i <图标文件名.ico> 指定打包程序使用的图标(icon)文件

使用举例

pyinstaller –i curve.ico –F SevenDigitsDrawV2.py

实例8: 科赫雪花小包裹

科赫雪花

高大上的分形几何

  • 分形几何是一种迭代的几何图形,广泛存在于自然界中

科赫曲线,也叫雪花曲线

    #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 = 3 # 3阶科赫雪花,阶数
koch(400,level)
turtle.right(120)
koch(400,level)
turtle.right(120)
koch(400,level)
turtle.hideturtle()
main()

python学习笔记(5)的更多相关文章

  1. python学习笔记整理——字典

    python学习笔记整理 数据结构--字典 无序的 {键:值} 对集合 用于查询的方法 len(d) Return the number of items in the dictionary d. 返 ...

  2. VS2013中Python学习笔记[Django Web的第一个网页]

    前言 前面我简单介绍了Python的Hello World.看到有人问我搞搞Python的Web,一时兴起,就来试试看. 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环 ...

  3. python学习笔记之module && package

    个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ...

  4. python学习笔记(六)文件夹遍历,异常处理

    python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ...

  5. python学习笔记--Django入门四 管理站点--二

    接上一节  python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...

  6. python学习笔记--Django入门0 安装dangjo

    经过这几天的折腾,经历了Django的各种报错,翻译的内容虽然不错,但是与实际的版本有差别,会出现各种奇葩的错误.现在终于找到了解决方法:查看英文原版内容:http://djangobook.com/ ...

  7. python学习笔记(一)元组,序列,字典

    python学习笔记(一)元组,序列,字典

  8. Pythoner | 你像从前一样的Python学习笔记

    Pythoner | 你像从前一样的Python学习笔记 Pythoner

  9. OpenCV之Python学习笔记

    OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书< ...

  10. python学习笔记(五岁以下儿童)深深浅浅的副本复印件,文件和文件夹

    python学习笔记(五岁以下儿童) 深拷贝-浅拷贝 浅拷贝就是对引用的拷贝(仅仅拷贝父对象) 深拷贝就是对对象的资源拷贝 普通的复制,仅仅是添加了一个指向同一个地址空间的"标签" ...

随机推荐

  1. Ubuntu 18.04 记录

    登录后死机,关机时死机的解决方法 更新内核并安装 Nvidia 显卡驱动可解决. 在内核更新为 4.15.18,Nvidia 显卡驱动为 390 时,问题解决. 使用 LiveCD 启动,然后 mou ...

  2. matplotlib 生成 eps 插入到 tex

    matplotlib 生成 eps 插入到 tex matplotlib 生成 eps,就可以插入到 tex 中,而且是矢量图,放大不失真. 而且因为图中的元素都是嵌入到 pdf 中,所以图中的文字也 ...

  3. Selenium-Switch--切换浏览器tab/iframe/alart

    Switch 我们在UI自动化测试时,总会出现新建一个tab页面.弹出一个浏览器级别的弹框或者是出现一个iframe标签,这时我们用WebDriver提供的Api接口就无法处理这些情况了.需要用到Se ...

  4. Reinforcement Learning Solutions Ed2 Chapter 1 - 2 问题解答

    RL到了第三章题目多的不可思议 前两章比较简单,就在博客随便写写了.之后的用pdf更新. 1.1: Self-play will result different move even from the ...

  5. 发送邮件工具类MailHelper

    using System; using System.Net; using System.Net.Mail; using System.Text; using System.Threading; na ...

  6. C++多线程join同步问题

    其实就是想记录一下自己的想法,就是关于多个线程的执行顺序的思考.之前一直觉得std::thread::join会阻塞其他线程的运行,其实并不是这样子的.举个例子 std::vector<std: ...

  7. 程序员不能忍996了!全民 fuck ,GitHub来说话

    前两天有个Github超级火的一个项目,在一小时之内星标上千. https://github.com/997icu/996.ICU   截至目前 这个项目start数量超过63K.Issues5000 ...

  8. JQuery插件:ScrollTo平滑滚动到页面指定位置

    1.准备jQuery库和scrollTo.js插件. <script type="text/javascript" src="js/jquery.js"& ...

  9. UVA1449 Dominating Patterns

    UVA1449 Dominating Patterns 题目描述 有N个由小写字母组成的模式串以及一个文本串T.每个模式串可能会在文本串中出现多次.你需要找出哪些模式串在文本串T中出现的次数最多. 输 ...

  10. unity中加载场景不销毁以及切换场景重复实例化

    问题描述 游戏开发中会有多个场景,有时会有这样的需求,我们需要保证场景跳转但是需要保持某个游戏对象不被销毁,比如:音乐 实现思路 unity中提供了DontDestroyOnLoad(),这个API ...