python 函数和 lambda 表达式
一、函数
1. 定义函数
语法格式:
def 函数名(形参列表):
// 由零条到多条可执行语句组成的函数
[return [返回值]]
2. 调用函数
3. 为函数提供文档
help()函数:help(函数名)
__ doc__属性:print(函数名. __ doc __ )
4. 多个返回值
代码如下:
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. 递归函数
代码如下:
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))
二、函数的参数
1. 关键字(keyword)参数
# 定义一个函数
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))
2. 参数默认值
语法格式:
形参名 = 默认值
代码如下:
# 为两个参数指定默认值
def say_hi(name = "孙悟空", message = "欢迎来到疯狂软件")
3. 参数收集(个数可变的参数)
在形参前面添加一个星号(*),意味着该参数可接收多个参数值,多个参数值被当成元组传入。
代码如下:
# 定义了支持参数收集的函数
def test(a, *books):
print(books)
# books被当成元组处理
for b in books :
print(b)
#输出整数变量a的值
print (a)
# 调用test()函数
test (5, "疯狂iOS讲义", "疯狂Android讲义")
>> ('疯狂iOS讲义', '疯狂Android讲义')
>> 疯狂iOS讲义
>> 疯狂Android讲义
>> 5
#定义了支持参数收集的函数
def test(*books ,num):
print(books)
# books被当成元组处理
for b in books :
print(b)
print(num)
#调用testO函数
test ("疯狂iOS讲义", "疯狂 Android讲义", num = 20)
>> ('疯狂iOS讲义', '疯狂 Android讲义')
>> 疯狂iOS讲义
>> 疯狂 Android讲义
>> 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)
>> 1 2 3
>> ('疯狂 iOS 讲义', '疯狂Android讲义')
>> {'语文': 89, '数学': 94}
test(1, 2, "疯狂 iOS 讲义", "疯狂Android讲义", 语文=89, 数学=94)
>> 1 2 '疯狂 iOS 讲义'
>> ('疯狂 iOS 讲义', '疯狂Android讲义')
>> {'语文': 89, '数学': 94}
test(1, 2, "疯狂Android讲义", 语文=89, 数学=94)
>> 1 2 3
>> ()
>> {'语文': 89, '数学': 94}
4. 逆向参数收集
代码如下:
def foo(name, *nums):
print ("name 参数:", name)
print ("nums 参数:", nums)
my_tuple = (1, 2, 3)
#梗用逆向收集,将my^tuple元组的元素传给nums参数
foo('fkif', *my_tuple)
>> name 参数: fkif
>> nums 参数: (1, 2, 3)
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)
>> 在swap函数里,a的值是9 ; b的值是6
>> 交换结束后,变量a的也是6 :变量b的值是9
def swap(dw):
# 下面代码实现dw的a、b两个元素的值交换
dw['a'], dw['b'] = dw['b'], dw['a']
print("在swap()函数里,a元素的值是", dw['a'], ": b 元素的值是", dw['b'])
dw = {'a': 6, 'b': 9}
swap(dw)
print("交换结束后,a 元素的值是", dw['a'], "; b 元素的值是", dw['b'])
>> 在swap()函数里,a元素的值是9 ; b元素的值是6
>> 交换结束后,a元素的值是9 . b元素的值是6
通过上面介绍可以得出如下两个结论:
- 不管什么类型的参数,在Python函数中对参数直接使用“=”符号赋值是没用的,直接使用“=”符号赋值并不能改变参数。
- 如果需要让函数修改某些数据,则可以通过把这些数据包装成列表、字典等可变对象,然后把列表、字典等可变对象作为参数传入函数,在函数中通过列表、字典的方法修改它们,这样才能改变这些数据。
6. 变量作用域
在程序中定义一个变量时,这个变量是有作用范围的,变量的作用范围被称为它的作用域。根据定义变量的位置,变量分为两种。
- 局部变量。在函数中定义的变量,包括参数,都被称为局部变量。
- 全局变量。在函数外面、全局范围内定义的变量,被称为全局变量。
实际上,Python提供了如下三个工具函数来获取指定范围内的“变量字典”。
- globals():该函数返回全局范围内所有变量组成的“变量字典”。
- locals():该函数返回当前局部范围内所有变量组成的"变量字典”。
- vars(object):获取在指定对象范围内所有变量组成的“变量字典”。如果不传入object参数,vars()和locals。的作用完全相同。
globals()和locals()看似完全不同,但它们实际上也是有联系的,关于这两个函数的区别和联系大致有以下两点。
-
locals()总是获取当前局部范围内所有变量组成的“变量字典",因此,如果在全局范围内(在函数之外)调用locals()函数,同样会获取全局范围内所有变量组成的“变量字典;而globals()无论在哪里执行,总是获取全局范围内所有变量组成的“变量字典”。
-
一般来说,使用locals()和globals()获取的“变量字典”只应该被访问,不应该被修改。但实际上,不管是使用globals()还是使用locals()获取的全局范围内的“变量字典”,都可以被修改,而这种修改会真正改变全局变量本身:但通过locals()获取的局部范围内的“变量字典”,’即使对它修改也不会影响局部变量。下面程序示范了如何使用locals()、globals()函数访问局部范围和全局范围内的“变量字典"。
代码如下:
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
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'] = 996
print(x) # 输出 99
(1)访问被遮蔽的全局变量
代码如下:
name = 'Charlie'
def test ():
# 通过globals()函数访问name全局变量
print(globals()['name']) # Charlie
name = '孙悟空'
test()
print(name) # Charlie
>> Charlie
>> Charlie
(2)在函数中申明全局变量
代码如下:
name = 'Charlie'
def test ():
# 声明name是全局变量,后面的赋值语句不会重新定义局部变量
global name
#直接访问name全局变量
print(name) # Charlie
name = '孙悟空'
test()
print(name) # 孙悟空
>> Charlie
>> 孙悟空
三、局部函数
1. global关键字
定义函数时,在函数内部对函数外的变量进行操作,声明访问全局变量
global name
2. nonlocal关键字
在函数或其他作用域中使用外层(非全局)变量,声明访问局部变量
nonlocal name
代码如下:
# 定义函数,该函数会包含局部函数
def get_math_func(type, nn):
# 定又一个弄算平方的局部函数
def square (n):
return n * n
# 定义一个计算立方的局部函数6666
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)) # 输出6
print(get_math_func("cube", 3)) # 输出 27
print(get_math_func("", 3)) # 输出 6
四、函数的高级内容
使用函数变量
使用函数作为函数形参
使用函数作为返回值
五、局部函数与lambda表达式
lambda表达式可以在程序中被传递和调用
表达式:lambda [parameter_list(参数)]:表达式
参数可以忽略,单行函数体的函数
代码如下
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表达式,可以使程序更加简洁,而且性能更好。
代码如下:
# 传入计算平方的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]