函数和lambda表达式
5.1函数
一个程序可以由很多个函数组成
5.1.1定义函数和调用函数
## 定义一个函数,声明2个形参
#def my_max(x, y) :
# # 定义一个变量z,该变量等于x、y中较大的值
# z = x if x > y else y
# # 返回变量z的值
# return z
def my_max(x, y) :
# 返回一个表达式
return x if x > y else y
# 定义一个函数,声明一个形参
def say_hi(name) :
print("===正在执行say_hi()函数===")
return name + ",您好!"
a = 6
b = 9
# 调用my_max()函数,将函数返回值赋值给result变量
result = my_max(a , b) # ①
print("result:", result)
# 调用say_hi()函数,直接输出函数的返回值
print(say_hi("孙悟空")) # ②
5.1.2为函数提供文档
def my_max(x, y) :
'''
获取两个数值之间较大数的函数。
my_max(x, y)
返回x、y两个参数之间较大的那个
'''
# 定义一个变量z,该变量等于x、y中较大的值
z = x if x > y else y
# 返回变量z的值
return z
# 使用help()函数查看my_max的帮助文档
help(my_max)
print(my_max.__doc__)
5.1.3多个返回值
def sum_and_avg(list):
sum = 0
count = 0
for e in list:
# 如果元素e是数值
if isinstance(e, int) or isinstance(e, float):
count += 1
sum += e
return sum, sum / count
my_list = [20, 15, 2.8, 'a', 35, 5.9, -1.8]
# 获取sum_and_avg函数返回的多个值,多个返回值被封装成元组
tp = sum_and_avg(my_list) #①
print(tp)
# 使用序列解包来获取多个返回值
s, avg = sum_and_avg(my_list) #②
print(s)
print(avg)
5.1.4递归函数
def fn(n) :
if n == 0 :
return 1
elif n == 1 :
return 4
else :
# 函数中调用它自身,就是函数递归
return 2 * fn(n - 1) + fn(n - 2)
# 输出fn(10)的结果
print("fn(10)的结果是:", fn(10))
5.2函数的参数
谁使用函数,谁负责传入参数值
5.2.1关键字参数
# 定义一个函数
def girth(width , height):
print("width: ", width)
print("height: ", height)
return 2 * (width + height)
# 传统调用函数的方式,根据位置传入参数
print(girth(3.5, 4.8))
# 根据关键字参数来传入参数
print(girth(width = 3.5, height = 4.8))
# 使用关键字参数时可交换位置
print(girth(height = 4.8, width = 3.5))
# 部分使用关键字参数,部分使用位置参数
print(girth(3.5, height = 4.8))
# 位置参数必须放在关键字参数之前,下面代码错误
print(girth(width = 3.5, 4.8))
5.2.2参数默认值
# 为两个参数指定默认值
def say_hi(name = "孙悟空", message = "欢迎来到疯狂软件"):
print(name, ", 您好")
print("消息是:", message)
# 全部使用默认参数
say_hi()
# 只有message参数使用默认值
say_hi("白骨精")
# 两个参数都不使用默认值
say_hi("白骨精", "欢迎学习Python")
# 只有name参数使用默认值
say_hi(message = "欢迎学习Python")
say_hi("欢迎学习Python")
#say_hi(name="白骨精", "欢迎学习Python")
#say_hi("欢迎学习Python" , name="白骨精")
say_hi("白骨精", message="欢迎学习Python")
say_hi(name="白骨精", message="欢迎学习Python")
# 定义一个打印三角形的函数,有默认值的参数必须放在后面
def printTriangle(char, height = 5) :
for i in range(1, height + 1) :
# 先打印一排空格
for j in range(height - i) :
print(' ', end = '')
# 再打印一排特殊字符
for j in range(2 * i - 1) :
print(char, end = '')
print()
printTriangle('@', 6)
printTriangle('#', height=7)
printTriangle(char = '*')
5.2.3 参数收集(个数可变的参数)
# 定义了支持参数收集的函数
def test(a, *books) :
print(books)
# books被当成元组处理
for b in books :
print(b)
# 输出整数变量a的值
print(a)
# 调用test()函数
test(5 , "疯狂iOS讲义" , "疯狂Android讲义")
# 定义了支持参数收集的函数
def test(*books ,num) :
print(books)
# books被当成元组处理
for b in books :
print(b)
print(num)
# 调用test()函数
test("疯狂iOS讲义", "疯狂Android讲义", num = 20)
my_list = ["疯狂Swift讲义", "疯狂Python讲义"]
# 将列表的多个元素传给支持参数收集的参数
test(my_list, num = 20)
my_tuple= ("疯狂Swift讲义", "疯狂Python讲义")
# 将元组的多个元素传给支持参数收集的参数
test(*my_tuple, num = 20)
# 定义了支持参数收集的函数
def test(x, y, z=3, *books, **scores) :
print(x, y, z)
print(books)
print(scores)
test(1, 2, 3, "疯狂iOS讲义" , "疯狂Android讲义", 语文=89, 数学=94)
test(1, 2, "疯狂iOS讲义" , "疯狂Android讲义", 语文=89, 数学=94)
test(1, 2, 语文=89, 数学=94)
5.2.4 逆向参数收集
def test(name, message):
print("用户是: ", name)
print("欢迎消息: ", message)
my_list = ['孙悟空', '欢迎来疯狂软件']
test(*my_list)
def foo(name, *nums):
print("name参数: ", name)
print("nums参数: ", nums)
my_tuple = (1, 2, 3)
# 使用逆向收集,将my_tuple元组的元素传给nums参数
foo('fkit', *my_tuple)
# 使用逆向收集,将my_tuple元组的第一个元素传给name参数,剩下参数传给nums参数
foo(*my_tuple)
# 不使用逆向收集,my_tuple元组整体传给name参数
foo(my_tuple)
def bar(book, price, desc):
print(book, " 这本书的价格是: ", price)
print('描述信息', desc)
my_dict = {'price': 89, 'book': '疯狂Python讲义', 'desc': '这是一本系统全面的Python学习图书'}
# 按逆向收集的方式将my_dict的多个key-value传给bar()函数
bar(**my_dict)
5.2.5函数的参数传递机制
def swap(a , b) :
# 下面代码实现a、b变量的值交换
a, b = b, a
print("swap函数里,a的值是", \
a, ";b的值是", b)
a = 6
b = 9
swap(a , b)
print("交换结束后,变量a的值是", \
a , ";变量b的值是", b)
当参数是一个可变对象(列表、字典等)
def swap(dw):
# 下面代码实现dw的a、b两个元素的值交换
dw['a'], dw['b'] = dw['b'], dw['a']
print("swap函数里,a元素的值是",\
dw['a'], ";b元素的值是", dw['b'])
# 把dw直接赋值为None,让它不再指向任何对象
dw = None
dw = {'a': 6, 'b': 9}
swap(dw)
print("交换结束后,a元素的值是",\
dw['a'], ";b元素的值是", dw['b'])
5.2.6变量作用域
函数执行时 系统会分配一个“临时内存空间”,局部变量保存在其中,函数执行后,临时内存空间也释放
全局变量和局部变量他们的变量名和值像一个 “看不见”的字典,变量名是key 值是value
- globals(): 该函数返回全局范围内所有变量组成的“变量字典”
- locals(): 该函数返回局部范围内所有变量组成的“变量字典”
- vars(object): 获取指定对象范围内所有变量组成的“变量字典”
def test():
age = 20
# 直接访问age局部变量
print(age) # 输出20
# 访问函数局部范围的“变量数组”
print(locals()) # {'age': 20}
# 通过函数局部范围的“变量数组”访问age变量
print(locals()['age']) # 20
# 通过locals函数局部范围的“变量数组”改变age变量的值
locals()['age'] = 12
# 再次访问age变量的值
print('xxx', age) # 依然输出20
# 通过globals函数修改x全局变量
globals()['x'] = 19
test();
x = 5
y = 20
print(globals()) # {..., 'x': 5, 'y': 20}
# 在全局访问内使用locals函数,访问的是全局变量的“变量数组”
print(locals()) # {..., 'x': 5, 'y': 20}
# 直接访问x全局变量
print(x) # 5
# 通过全局变量的“变量数组”访问x全局变量
print(globals()['x']) # 5
# 通过全局变量的“变量数组”对x全局变量赋值
globals()['x'] = 39
print(x) # 输出39
# 在全局范围内使用locals函数对x全局变量赋值
locals()['x'] = 99
print(x) # 输出99
name = 'Charlie'
def test ():
# 直接访问name全局变量
print(name) # Charlie
name = '孙悟空'
test()
print(name)
name = 'Charlie'
def test ():
# 直接访问name全局变量
print(globals()['name']) # Charlie
name = '孙悟空'
test()
print(name) # Charlie
name = 'Charlie'
def test ():
# 声明name是全局变量,后面的赋值语句不会重新定义局部变量
global name
# 直接访问name全局变量
print(name) # Charlie
name = '孙悟空'
test()
print(name) # 孙悟空
5.3局部函数
# 定义函数,该函数会包含局部函数
vdef get_math_func(type, nn) :
# 定义一个计算平方的局部函数
def square(n) : # ①
return n * n
# 定义一个计算立方的局部函数
def cube(n) : # ②
return n * n * n
# 定义一个计算阶乘的局部函数
def factorial(n) : # ③
result = 1
for index in range(2, n + 1) :
result *= index
return result
# 调用局部函数
if type == "square" :
return square(nn)
elif type == "cube":
return cube(nn)
else:
return factorial(nn)
print(get_math_func("square", 3)) # 输出9
print(get_math_func("cube", 3)) # 输出27
print(get_math_func("", 3)) # 输出6
通过nonlocal语句声明访问赋值语句只是访问该函数所在函数内的局部变量
def foo ():
# 局部变量name
name = 'Charlie'
def bar ():
nonlocal name
# 访问bar函数所在的foo函数的name局部变量
print(name) # Charlie
name = '孙悟空'
bar()
foo()
5.4函数的高级内容
函数本身也是一个对象,函数可以用于赋值,也可以用作其他函数的参数,还可以作为其他函数的返回值。
5.4.1使用函数变量
所有的函数都是function对象
# 定义一个计算乘方的函数
def pow(base, exponent) :
result = 1
for i in range(1, exponent + 1) :
result *= base
return result
# 将pow函数赋值给my_fun,则my_fun可当成pow使用
my_fun = pow
print(my_fun(3 , 4)) # 输出81
# 定义一个计算面积的函数
def area(width, height) :
return width * height
# 将area函数赋值给my_fun,则my_fun可当成area使用
my_fun = area
print(my_fun(3, 4)) # 输出12
5.4.2 使用函数作为函数形参
# 定义函数类型的形参,其中fn是一个函数
def map(data, fn) :
result = []
# 遍历data列表中每个元素,并用fn函数对每个元素进行计算
# 然后将计算结果作为新数组的元素
for e in data :
result.append(fn(e))
return result
# 定义一个计算平方的函数
def square(n) :
return n * n
# 定义一个计算立方的函数
def cube(n) :
return n * n * n
# 定义一个计算阶乘的函数
def factorial(n) :
result = 1
for index in range(2, n + 1) :
result *= index
return result
data = [3 , 4 , 9 , 5, 8]
print("原数据: ", data)
# 下面程序代码3次调用map()函数,每次调用时传入不同的函数
print("计算数组元素的平方")
print(map(data , square))
print("计算数组元素的立方")
print(map(data , cube))
print("计算数组元素的阶乘")
print(map(data , factorial))
# 获取map的类型
print(type(map))
5.4.3使用函数作为返回值
def get_math_func(type) :
# 定义一个计算平方的局部函数
def square(n) : # ①
return n * n
# 定义一个计算立方的局部函数
def cube(n) : # ②
return n * n * n
# 定义一个计算阶乘的局部函数
def factorial(n) : # ③
result = 1
for index in range(2 , n + 1):
result *= index
return result
# 返回局部函数
if type == "square" :
return square
if type == "cube" :
return cube
else:
return factorial
# 调用get_math_func(),程序返回一个嵌套函数
math_func = get_math_func("cube") # 得到cube函数
print(math_func(5)) # 输出125
math_func = get_math_func("square") # 得到square函数
print(math_func(5)) # 输出25
math_func = get_math_func("other") # 得到factorial函数
print(math_func(5)) # 输出120
5.5局部函数与lambda表达式
5.1.1 使用lambda表达式代替局部函数
def get_math_func(type) :
result=1
# 该函数返回的是Lambda表达式
if type == 'square':
return lambda n: n * n # ①
elif type == 'cube':
return lambda n: n * n * n # ②
else:
return lambda n: (1 + n) * n / 2 # ③
# 调用get_math_func(),程序返回一个嵌套函数
math_func = get_math_func("cube")
print(math_func(5)) # 输出125
math_func = get_math_func("square")
print(math_func(5)) # 输出25
math_func = get_math_func("other")
print(math_func(5)) # 输出15.0
a = lambda x, y: x + y
def add(x, y): return x+ y
# 传入计算平方的lambda表达式作为参数
x = map(lambda x: x*x , range(8))
print([e for e in x]) # [0, 1, 4, 9, 16, 25, 36, 49]
# 传入计算平方的lambda表达式作为参数
y = map(lambda x: x*x if x % 2 == 0 else 0, range(8))
print([e for e in y]) # [0, 0, 4, 0, 16, 0, 36, 0]