Python入门 函数 提高篇
一、匿名函数 lambda
lambda 匿名函数,他是一种比def更简单的函数,该函数的定义逻辑非常简单,函数体只能有一个表达式,返回结果为表达式的值。
1、lambda 匿名函数定义
lambda [参数1[,参数2,.....参数n]]:表达式
实例:
g = lambda x:x*x+1
print(g(1)) # 结果为2
print(g(3)) # 结果为10
释:可以这样认为,lambda作为一个表达式,定义了一个匿名函数,上例的代码x为入口参数,x*x+1为函数体,用函数来表示为:
def g(x):
return x*x+1
非常容易理解,在这里lambda简化了函数定义的书写形式。是代码更为简洁,但是使用函数的定义方式更为直观,易理解。
2、lambda 匿名函数的 if...else..
lambda expression1 if condition else expression2
释义:如果condition 为True,条件表达式的结果为expression1,否则为expression2
示例:
funmax = lambda x, y: x if x > y else y # 求两个数最大值
# 如果 x>y 则返回x,否则返回y
print(funmax(5, 6))
# 递归求n!
func = lambda n: 1 if n == 0 else n * func(n - 1)
print(func(5))
注意:lambda 并不会给程序运行效率的提高,只会使代码简洁些,非常简单的函数可以使用lambda。 如果需要使用到for...in...或if...else... ,最好不用lambda,它对代码的可读性和可重用性影响很大。 复杂的lambda是逗B用来炫技的。
3、lambda 匿名函数灵活运用
lambda 匿名函数使Python3的有些类和函数使用更加灵活。如:filter, map, reduce
filter(function,sequence) 过滤筛选类,他能过滤筛选序列中的数据,Python2返回list列表,Python3返回可迭代对象。
map(function,sequence) 将function调用映射到每个序列的对应元素上,Python2返回所有值的列表,Python3返回可迭代对象。
reduce(function,sequence,[initial]) 累积函数,function有两个参数,如无initial值,取sequence第一个元素与第二个为function参数,有则initial值作为第一个参数,sequence的第一个参数作为第二个参数。function返回值作为下次调用的第一个参数,取sequence中没选取的后一个参数作为函数第二个参数,依次类推将结果积累返回。
示例:
list1 = [1, 18, 9, 7, 17, 12, 6]
f = filter(lambda x: x % 2 == 0, list1) # 筛选list1中能被2整除的数据,返回值可迭代对象
print(list(f)) # 转换为list 打印出结果
m = map(lambda x: x * 2 + 10, list1) # 对list中的每个值进行操作,返回可迭代对象
print(list(m))
from functools import reduce
r = reduce(lambda x, y: x + y, list1) # 对list中元素进行累积,相当于((((((1+18)+9)+7)+17)+12)+6)
print(r)
r = reduce(lambda x, y: x + y, list1, 1) # 对list中元素进行累积,初始值为1,相当于 1+((((((1+18)+9)+7)+17)+12)+6)
print(r)
输出结果:
[18, 12, 6] [12, 46, 28, 24, 44, 34, 22]
70
71
二、Python函数的可变参数(*args, **kwargs)
如果想让一个函数能接受任意个参数,我们就可以定义一个可变参数。可变参数有序列可变与关键字可变。
1、*args 序列可变参数
序列可变参数定义格式如下:
def 函数名([参数,] *args):
函数体
return [返回值]
释:args加了星号(*)的参数名会存放所有未命名的不带键的参数,将这些参数转换为一个元组存储在args中。我们选择传入0~n个不带键的参数。
注意:序列可变参数中的args传入参数可以是元组或列表,也可以只不带关键字的任意多个参数。
示例:
def variablefun(name, *args):
print(name, end=':')
for arg in args:
print(arg, end=',')
print('')
variablefun('Bobo') # 可变参数可以不传入值
variablefun('woodman', 80, 90, 'man') # 可变参数可以传入任意值
tuple1 = ('女', 20)
# 元组或列表前无*可变参数将元组当成一个变量
variablefun('Helen', tuple1)
# 元组或列表前有信号,可变参数将元组中的值当成了多个参数
variablefun('Baby', *tuple1) # 注意观察结果和Helen 的区别
variablefun('Baby', '女', 20) # 加‘*’ 相当于传入两个值
输出结果:
Bobo: woodman:80,90,man, Helen:('女', 20), Baby:女,20, Baby:女,20,
注意:第7、8行 说明可变参数可以传入任意值;第11行调用函数variablefun('Helen', tuple1),传入的是整个元组,函数会认为是一个元组参数 ('女', 20);第13行variablefun('Baby', *tuple1)传入参数元组前加了星号,程序会将元组数据拆开,按照顺序传入数据,*tuple1 传入的是两个参数‘女’和 20 。
2、**kwargs 键对值可变型参数
序列可变参数定义格式如下:
def 函数名([参数,] **kwargs ):
函数体
return [返回值]
释:kwargs 加了星号(**)的参数名会存放所有未命名的带有键对值的变量参数,将这些参数转换为一个字典存储在kwargs 中。我们选择传入0~n个带有键值对的参数。
注意:键对值可变参数中的kwargs 传入参数可以是字典,也可以是任意带关键字的参数。
示例:
def fun(name, **kwargs):
print('name:', name)
for key, value in kwargs.items():
print(key, ':', value)
print('----------')
fun('woodman') # 可变参数可以不传入值
fun('Bob', sex='男') # 不在参数列表中的参数必须指定键值对
tuple1 = {'sex': '男', 'class': 2016012}
fun('Alan', **tuple1) # 可以传入字典,不要忘记**
tuple2 = {'name': 'Heln', 'sex': '女', 'score': 89}
fun(**tuple2)
输出结果:
name: woodman ---------- name: Bob sex : 男 ---------- name: Alan sex : 男 class : 2016012 ---------- name: Heln sex : 女 score : 89 ----------
注意:最后一行,我们将参数name也放入了字典tuple2中,通过**tuple2传入函数,这样也是可用的。
三、变量作用域
Python 中,程序的变量并不是在哪个位置都可以访问的,在哪里赋值决定了该变量的作用域。
Python的作用域一共有4种,分别是:
L (Local) 局部作用域
E (Enclosing) 闭包函数外的函数中
G (Global) 全局作用域
B (Built-in) 内建作用域
变量的查找以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这这些语句内定义的变量,外部也可以访问。
示例:
if True:
ifmsg = 'I am ifmsg'
print(ifmsg) # 可以在if外面访问msg
def fun():
funmsg = 'I am funmsg'
print(funmsg) # 不可以在函数外访问函数中的定义的变量
1、全局变量和局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。
示例:
total = 0 # 这是一个全局变量
total2 = 5
def sum(arg1, arg2):
print(total2) # 我们可以在函数体类访问全局变量,访问后不能对total2赋值
total = arg1 + arg2 # total在这里是局部变量
print("函数内是局部变量total : ", total)
return total
# 调用sum函数
sum(10, 20)
print("函数外是全局变量total : ", total)
输出结果:
5
函数内是局部变量total : 30
函数外是全局变量total : 0
注意:第4行print(total2)访问了total2,访问后我不能在对total2赋值; 第5行total = arg1 + arg2我们在函数内改变了total的值,total成为了函数内的局部变量,它并不会影响全局变量total 的值。
2、global 和 nonlocal关键字(了解)
当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了。
示例:
num = 123
def fun1():
global num # 使用 global 关键字声明,使num全局变量值可在函数内修改
print(num) # 输出为123
num = 456 # 修改全局变量值
fun1()
print(num) # 结果 456,全局变量值被修改
输出结果
123
456
如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了
示例:
def out():
num = 10 # out内部变量
def inner():
nonlocal num # nonlocal关键字声明
print(num)
num = 100 # 修改out内部变量
inner()
print(num)
out()
输出结果:
10
100
函数基础篇: Python入门 函数 基础篇
2019年3月28日,第一次修改,增加思维导图