【李刚-21天通关Python】第四章:函数
作者:互联网
【李刚-21天通关Python】第四章:函数
相关链接:
【李刚-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 b
return r
x = 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是参数
'''
pass
print(test.__doc__)
help(test)
多返回值函数与递归函数
一、多返回值函数
- 多返回值,本质就是返回元组
- 程序即可返回元组,也可直接返回多个值(系统会将其自动封装成元组)
import random
def 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")
return
elif n == 1:
return 1
else:
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 = 35
def info1 ():
# 局部变量
b = 'python'
print(b) # python
print(a) # 35
def info2 ():
# 局部变量
c = 'java'
print(b) # 错误,局部变量无法访问
print(a) # 35
二、获取变量字典
- globals() :该函数返回全局范围内所有变量组成的变量字典
- locals() :该函数返回当前局部范围内所有变量组成的变量字典
- vars(object) :获取指定对象的范围内所有变量组成的变量字典,如果不传入object参数,vars()和locals()的作用完全相同
三、变量遮蔽
- 全局变量默认可以在所有函数内访问
- 如果在函数中定义了与全局变量同名的变量,此时就会发生局部变量遮蔽(hide)全局变量的情形
name = 'python'
def info ():
# 依然访问全局变量name
pirnt(global()['name'])
# 在函数内对变量赋值,即定义新的name变量
name = 'java'
print(name)
info()
# python
# java
print(name) # python
name = 'python'
def info ():
# 声明name始终使用全局变量
global name
pirnt(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 name
print('name: ', name)
# 对封闭函数的局部变量的重新赋值
name = 'java'
print('name: ', name)
info()
print(name)
test()
# name: python
# name: java
# java
实操:定义计算N的阶乘的函数
方法一:使用循环
- 控制循环计数器从1循环到N
- 让循环计数器与前一个结果相乘,知道循环计数器等于N
def fract (n):
r = 1
if n < 1:
print("n不能小于1")
return
else:
for i in range(1, n+1):
r *= i
return r
print(fract(5)) # 120
print(fract(6)) # 720
方法二:递归
- N的阶乘等于N乘以N-1的阶乘
- N为1时,N的阶乘为1,保证递归有结束点
def fract (n):
if n < 1:
print("n不能小于1")
return
elif n == 1:
return 1
else:
# 递归:函数里调用函数自身
return fract(n) = fract(n-1) * n
print(fract(5)) # 120
print(fract(6)) # 720
方法三:使用 reduce 函数
- Python在functools模块提供了 reduce() 函数,该函数使用指定函数对序列对象进行累积
- 该函数的用法:reduce(function, sequence[, initial])
import functools
def fn (x, y):
return x * y
def fract (n):
if n < 1:
print("n不能小于1")
return
else:
return functools.reduce(fn, range(1, n+1))
# fn函数的另一种表示方法:lambda x, y: x * y
print(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 rt
print_matrix(matrix)
'''
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
'''
print_matrix(transform_matrix(matrix))
'''
1 5 9
2 6 10
3 7 11
4 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), ……
# 逆向参数收集,将矩阵中的多个列表转换成多个参数传给zip
return list(zip(*m))
print_matrix(matrix)
'''
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
'''
print_matrix(transform_matrix(matrix))
'''
1 5 9
2 6 10
3 7 11
4 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 numpy
return tolist(numpy.transpose(m))
print_matrix(matrix)
'''
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
'''
print_matrix(transform_matrix(matrix))
'''
1 5 9
2 6 10
3 7 11
4 8 12
'''
标签:bar,21,Python,函数,李刚,参数,print,def,name 来源: https://blog.csdn.net/weixin_43796325/article/details/98115684