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)
   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

 思维导图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值