【李刚-21天通关Python】第四章:函数

  • 第四章:函数
    • 函数入门与定义函数
    • 多返回值函数与递归函数
    • 关键字参数与参数默认值
    • 参数收集和逆向参数收集
    • 变量作用域
    • 局部函数
    • 实操:定义计算N的阶乘的函数
    • 实操:定义计算矩阵转置的函数

相关链接:
【李刚-21天通关Python-15】之 函数入门与定义函数
【李刚-21天通关Python-16】之 多返回值函数与递归函数
【李刚-21天通关Python-17】之 关键字参数与参数默认值
【李刚-21天通关Python-18】之 参数收集和逆向参数收集
【李刚-21天通关Python-19】之 变量作用域
【李刚-21天通关Python-20】之 局部函数
【李刚-21天通关Python-21】之 实操:定义计算N的阶乘的函数
【李刚-21天通关Python-22】之 实操:定义计算矩阵转置的函数


第四章:函数

函数入门与定义函数

一、函数的定义

  • 所谓函数,就是为一段实现特定功能的代码取个名字,以后即可通过该名字来执行(调用)这段代码

二、函数定义的定律

  • 函数需要几个关键的、需要动态变化的数据,这些数据就应定义成函数的参数
  • 函数需要传出几个重要的数据,这些数据应该定义成返回值
  • 函数的内部实现过程

三、函数语法

  • 在使用函数之前必须先定义函数,语法格式如下:
'''
def 函数名 (参数列表):# 由零条到多条可执行性语句组成的函数…… …… [return [返回值]]
'''

【例一】

def first ():print("first函数")for i in range(5):print(i)first()  # first函数 0 1 2 3 4

【例二】

def hello (name):print('hello 函数')print('您好,' + name)hello (python)
# hello 函数
# 您好,python

【例三】

def max (a, b):r = a if a > b else breturn rx = max(3, 5)
print(x)  # 5
x = max(100, 0)
print(x)  # 100

四、为函数提供文档

  • 只要把字符串放在一段函数声明之后、函数体之前,这段字符串就是函数的说明文档
  • Python内置的 help() 函数查看其他函数的帮助文档
  • 也可通过函数的 __doc__属性(双下划线)来查看函数的说明文档

(1)使用help()函数查看内置函数文档

(2)使用__doc__属性查看内置函数文档

(3)举例

def test (a):'''这是一个简单函数a是参数'''passprint(test.__doc__)
help(test)

多返回值函数与递归函数

一、多返回值函数

  • 多返回值,本质就是返回元组
  • 程序即可返回元组,也可直接返回多个值(系统会将其自动封装成元组)
import randomdef test ():# 生成三个随机的大写字符c1 = chr(random.randint(65,90))c2 = chr(random.randint(65,90))c3 = chr(random.randint(65,90))return (c1, c2, c3)# return r1, r2, r3

二、多返回值函数的用法

  • 获取多返回值函数的返回值时:
  • 即可用单个变量(元组)来获取
  • 也可用多个变量获取(元组解包)

三、递归函数

  • 函数体内调用它自身被称为函数的递归
  • 函数的递归包含了一种隐式的循环,他会重复执行某段代码,但这种重复执行无需循环控制
  • 注意点:
  • 向已知的方向递归
  • 让递归有结束的时候,不要无限递归
# 计算n的阶乘
def frac (n):if n < 1:print("n不能小于1")returnelif n == 1:return 1else:return frac(n - 1) * n print(frac(5))  # 120
print(frac(6))  # 720

关键字参数与参数默认值

一、关键字参数

  • Python函数的参数名不是没有意义的,Python允许调用函数时通过名字来传入参数值
  • 调用函数时,支持两种方式为参数指定值:
  • 位置参数:必须按顺序为每个参数指定参数值
  • 关键字参数(命名参数):按参数名为参数指定参数值
def info (name, age, height):print("name: ", name)print("age: ", age)print("height: ", height)# 位置参数
info('python', 18, 180)
# 关键字参数
# 优势:不需要按顺序,可读性更高
info(age=18, name='python',height=180)
# 混合使用
# 注意:关键字参数必须在位置参数之后
info('python', height=180, age=18)

二、参数的默认值

  • 程序需要在定义函数时为一个或多个形参指定默认值——这样调用函数时就可以省略为该形参传入参数值,而是直接使用该形参的默认值
  • 为形参指定默认值的语法格式为:形参名 = 默认值
def info (age, name='python'):print("name的参数为:", name)print("age的参数为:", age)info(18)
# name的参数为:python
# age的参数为:18
info(20, 'java')
# name的参数为:java
# age的参数为:20
def say_hi(name='孙悟空', message='您好,欢迎学习Python'):print("name: ", name)print("message: ", message)say_hi()
# name: 孙悟空
# message: 您好,欢迎学习Python
say_hi('白骨精')
# name: 白骨精
# message: 您好,欢迎学习Python
say_hi(message='欢迎加入大家庭')
# name: 孙悟空
# message: 欢迎加入大家庭

参数收集和逆向参数收集

一、普通参数收集

  • 在形参前面添加一个星号(“ * ”),这样就意味着该参数可接收多个参数值,多个参数值被当作元组传入
  • 参数收集的本质就是一个元组:Python会将传给带“*”参数的多个值收集成一个元组
  • Python允许个数可变的形参可以处于形参列表的任意位置,但最多只能带一个支持普通参数收集的形参
  • 如果支持普通参数收集的形参位于前面,后面参数则需要使用关键字参数传值
def test (num, *books):print("num: ", num)print("books: ", books)test(3, 'python', 'java', 'cpp')
# num: 3
# books: ('python', 'java', 'cpp')
def info (*names, msg):for name in names:print("%s, %s" % (name, msg))info('孙悟空', '猪八戒', '牛魔王', msg='欢迎大家')
# 孙悟空,欢迎大家
# 猪八戒,欢迎大家
# 牛魔王,欢迎大家

二、关键字参数收集

  • 在参数前面添加两个星号,该参数支持关键字参数收集,收集的参数被当成dict处理
  • 一个函数可同时支持普通参数收集和关键字参数收集
def test (num, *books, **scores):print("num: ", num)print("books: ",books)print("scores: ", scores)test(5, 'python', 'java', 'cpp', 语文=90, 数学=100)
# num: 5
# books: ('python', 'java', 'cpp')
# scores: {'语文':90, '数学':100}
def info (*names, msg, **scores):for name in names:print("%s, %s" % (name, msg))print(scores)# dict的参数收集:只收集不能明确传入的关键字参数
info('孙悟空', '猪八戒', '牛魔王', msg='欢迎大家', 语文=90, 数学=100)
# 孙悟空,欢迎大家
# 猪八戒,欢迎大家
# 牛魔王,欢迎大家
# {'语文':90, '数学':100}

三、逆向参数收集

  • 逆向参数收集:在元组、列表前添加“*”,在字典之前添加“**”
  • 即使是支持收集的参数,如果程序需要将一个元组传给该参数,同样需要使用逆向收集
def test (a, b):print(a)print(b)vals = (20, 40)
msgs = ['aa', 'bb']
dicts = {'a': 80, 'b': 90}
# *对元组进行解包(逆向参数收集)
test(*vals)
# 20
# 40
test(*msgs)
# aa
# bb
test(**dicts)
# 80
# 90

变量作用域

一、变量作用域

  • 根据定义变量的位置,变量的作用域有两种:
  • 局部变量:在函数中定义的变量包括参数
  • 全局变量:在函数外面、全局范围内定义的变量
# 全局变量
a = 35def info1 ():# 局部变量b = 'python'print(b)  # pythonprint(a)  # 35def info2 ():# 局部变量c = 'java'print(b)  # 错误,局部变量无法访问print(a)  # 35

二、获取变量字典

  • globals() :该函数返回全局范围内所有变量组成的变量字典
  • locals() :该函数返回当前局部范围内所有变量组成的变量字典
  • vars(object) :获取指定对象的范围内所有变量组成的变量字典,如果不传入object参数,vars()和locals()的作用完全相同

三、变量遮蔽

  • 全局变量默认可以在所有函数内访问
  • 如果在函数中定义了与全局变量同名的变量,此时就会发生局部变量遮蔽(hide)全局变量的情形
name = 'python'
def info ():# 依然访问全局变量namepirnt(global()['name'])  # 在函数内对变量赋值,即定义新的name变量name = 'java'print(name)  info()
# python
# java
print(name)  # python
name = 'python'
def info ():# 声明name始终使用全局变量global namepirnt(name)  # 对全局变量name重新赋值name = 'java'print(name)  info()
# python
# java
print(name)  # java

局部函数

一、局部函数

  • 放在函数体内定义的函数成为局部函数
  • 在默认情况下,局部函数对外部是隐藏的,局部函数只能在其封闭函数内使用
def foo ():print('foo函数')# 局部函数def bar ():for i in range(3):print('bar函数')# 局部函数只在其封闭函数内有效bar()foo()
# foo函数
# bar函数
# bar函数
# bar函数

二、封闭函数返回局部函数

  • 封闭函数可以返回局部函数,以便程序在其他作用域中使用局部函数
  • 如果封闭函数没有将局部函数返回出来,那么局部函数将只能在封闭函数内调用
def foo ():print('foo函数')# 局部函数def bar ():for i in range(3):print('bar函数')# bar返回函数本身(函数也相当于一个值,类型为function)# return bar() 表示返回bar函数的执行结果return bar# foo()函数的返回值是bar()函数,因此此处是用变量r来保存bar函数
r = foo()
r()
# foo函数
# bar函数
# bar函数
# bar函数
print(type(r))  # <class 'function'># foo()函数调用之后返回bar函数,而bar函数本身也可以调用
# ‘foo()’ = ‘bar’  ‘foo()()’ = ‘bar()’
foo()()
# foo函数
# bar函数
# bar函数
# bar函数

三、局部函数的遮蔽

  • 局部函数内的变量也会遮蔽它所在的封闭函数的局部变量
  • 局部函数为了避免遮蔽函数所在封闭函数的局部变量,可使用 nonlocal 进行声明
def test ():name = 'python'def info ():print('info函数')# 声明变量name是引用所在封闭函数内的局部变量nonlocal nameprint('name: ', name)# 对封闭函数的局部变量的重新赋值name = 'java'print('name: ', name)info()print(name)test()
# name: python
# name: java
# java

实操:定义计算N的阶乘的函数

方法一:使用循环

  • 控制循环计数器从1循环到N
  • 让循环计数器与前一个结果相乘,知道循环计数器等于N
def fract (n):r = 1if n < 1:print("n不能小于1")returnelse:for i in range(1, n+1):r *= ireturn rprint(fract(5))  # 120
print(fract(6))  # 720

方法二:递归

  • N的阶乘等于N乘以N-1的阶乘
  • N为1时,N的阶乘为1,保证递归有结束点
def fract (n):if n < 1:print("n不能小于1")returnelif n == 1:return 1else:# 递归:函数里调用函数自身return fract(n) = fract(n-1) * nprint(fract(5))  # 120
print(fract(6))  # 720

方法三:使用 reduce 函数

  • Python在functools模块提供了 reduce() 函数,该函数使用指定函数对序列对象进行累积
  • 该函数的用法:reduce(function, sequence[, initial])
import functoolsdef fn (x, y):return x * ydef fract (n):if n < 1:print("n不能小于1")returnelse:return functools.reduce(fn, range(1, n+1))# fn函数的另一种表示方法:lambda x, y: x * yprint(fract(5))  # 120
print(fract(6))  # 720

实操:定义计算矩阵转置的函数

方法一:嵌套循环转置

  • 首先创建一个长度与原矩阵第一个元素长度相等的新列表
  • 使用遍历原矩阵的每个元素(每个元素都是列表),再使用嵌套循环遍历每个元素,将列表中的元素添加到新列表对应的列表元素中
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]def print_matrix (m):for ele in m:for e in ele:print("%2d" % e, end=' ')print('')def transform_matrix (m):# m[0]有几个元素代表原矩阵有几列rt = [[] for i in m[0]]for ele in m:for i in range(len(ele)):# rt[i]代表新矩阵的第i行# ele[i]代表原矩阵当前行的第i列rt[i].append(ele[i])return rtprint_matrix(matrix)
'''1   2   3   45   6   7   89  10  11  12
13  14  15  16
'''print_matrix(transform_matrix(matrix))
'''1   5   92   6  103   7  114   8  12
'''

方法二:使用zip函数转置

  • zip 函数的作用是合并多个序列:多个序列第一个元素合并成第一个元素,多个序列第二个元素合并成第二个元素,……
  • 运用逆向参数收集
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]def print_matrix (m):for ele in m:for e in ele:print("%2d" % e, end=' ')print('')def transform_matrix (m):# zip([1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]) -> (1, 5, 9), ……# 逆向参数收集,将矩阵中的多个列表转换成多个参数传给zipreturn list(zip(*m))print_matrix(matrix)
'''1   2   3   45   6   7   89  10  11  12
13  14  15  16
'''print_matrix(transform_matrix(matrix))
'''1   5   92   6  103   7  114   8  12
'''

方法三:使用numpy模块转置

  • numpy模块提供了 transpose() 函数执行转置,该函数返回值是numpy的内置类型:array
  • 调用array的 tolist() 方法即可将array转换为list列表
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]def print_matrix (m):for ele in m:for e in ele:print("%2d" % e, end=' ')print('')def transform_matrix (m):import numpyreturn tolist(numpy.transpose(m))print_matrix(matrix)
'''1   2   3   45   6   7   89  10  11  12
13  14  15  16
'''print_matrix(transform_matrix(matrix))
'''1   5   92   6  103   7  114   8  12
'''

【李刚-21天通关Python】第四章:函数相关推荐

  1. 【李刚-21天通关Python】第一章:Python入门与字符串

    [李刚-21天通关Python]第一章:Python入门与字符串 第一章:Python入门与字符串 数据类型 字符串 运算符 实操:简易计算器 & 进制转换 章节分篇链接: [李刚-21天通关 ...

  2. 【李刚-21天通关Python-03】之 运算符

    [李刚-21天通关Python-03]之 运算符 一.赋值运算符 1.赋值运算符是 "=" 2.作用:将等号右边的值"装入"左边的变量中 二.算术运算符 算术运 ...

  3. 【李刚-21天通关Python-27】之 案例实操:函数装饰器应用

    [李刚-21天通关Python-27]之 案例实操:函数装饰器应用 一.函数装饰器的广泛应用 @staticmethod 和 @classmethod 的本质就是函数装饰器 staticmethod ...

  4. 【李刚-21天通关Python-23】之 定义类

    [李刚-21天通关Python-23]之 定义类 一.类和对象 两个重要概念:类(class)和对象(object,也被称为实例,instance) 类是某一批对象的抽象,可以将类理解成某种概念 对象 ...

  5. 视频教程-21天通关Python(课+书,含邮寄)-Python

    21天通关Python(课+书,含邮寄) 专注提供优质教学内容 CSDN就业班 ¥119.00 立即订阅 扫码下载「CSDN程序员学院APP」,1000+技术好课免费看 APP订阅课程,领取优惠,最少 ...

  6. 【python第四章——序列(列表、元组、字典、集合、字符串、正则)】

    python第四章--序列 第四章--序列 4.1列表 4.2元组 4.3字典 4.4集合 4.5字符串(重要) 4.6正则表达式 第四章--序列 概念:序列指一块可存放多个值的连续内存空间,这些值按 ...

  7. 【python第五章——函数】

    python第五章--函数 第五章--函数 5.1函数概述 5.2 函数进阶 下面部分之后再写 5.3函数习题(一些小例子) 第五章--函数 5.1函数概述 快速入门: #定义函数 def func( ...

  8. Python(第四章) 序列的应用

    第四章 本章概览 在Python中序列是最基本的数据结构.它是一块用于存放多个值的连续内存空间.Python中内置了5个常用的序列结构,分别是:列表.元组.集合.字典.字符串,本章详细讲解列表.元组. ...

  9. Python第四章-字典

    第四章 字典-当索引不好用时 4.0     字典可以理解成是C++里的map,可以映射任何类型.字典这种结构类型称为映射(mapping).   字典是Python中唯一内建的映射类型,字典中的值并 ...

最新文章

  1. 好系统U盘启动来说一说win10系统有必要更新到最新版本吗?
  2. 最近后缀.Scaletto,.com}KBK,com}BET,.Fuchsi勒索病毒开始爆发…
  3. Resin服务器平台介绍
  4. 19 个 JavaScript 常用的简写技术
  5. EOS从入门到精通(四)
  6. Linux信号列表(非实时信号和实时信号)
  7. jointable 能加多个字段吗_Excel函数Countif、Countifs超级实用技巧,你真的都掌握吗?...
  8. 前端处理跨域的几种方式
  9. 编写基于事件的CQRS读取模型
  10. 解决报错: No candidates found for method call XXXX (方法没有调用者)
  11. java 机器码 虚拟机_Java虚拟机:源码到机器码
  12. JS DOM事件(常用消息、常用事件、addEventListener、removeEventListener)
  13. django从入门到放弃之001.初探
  14. C#XmlHelper操作Xml文档的帮助类
  15. 主板aspm关闭_【装机加人品】主板如何开启与关闭超线程技术?
  16. liferay-protal学习1-配置开发环境
  17. python下载文件并改名_用 Python 给下载的 B 站视频文件批量改名
  18. 【技术贴】【技术贴】每次双击都会跳出来打开方式的解决办法。。。选择你想用来打开此文件的程序。。...
  19. 深信服---之上网行为管理
  20. 按键精灵-随机获取不重复内容

热门文章

  1. STM32汉字字模制作详解(OLED实战)
  2. 小白推荐系统扫盲记——数据分析
  3. 4T移动硬盘 分区_Windows如何对硬盘进行分区?
  4. 电脑计算机u盘启动不了桌面图标,开机桌面图标不显示怎么办【解决方法】
  5. 在ListView中实现button功能
  6. 国家、省、市三级联动下拉列表
  7. 服务器中imm的作用,联想X系列服务器IMM2(集成管理模块)基本操作
  8. 一篇文章搞定DX9.0c 环境里的3DXSpriet !!
  9. 老式录像带VHS信号故障毛刺干扰特效AE/PR插件 Signal v1.2.3
  10. 快速学完计算机网络,如何让电脑网速变快 5分钟就学会