python(九):函数、匿名函数 lambda

函数

基础

参数、返回值均可为任意参数

def name(param1, param2, ..., paramN):
	"""文档字符串"""
    statements
    return/yield value 

和其他需要编译的语言(比如 C 语言)不一样的是,def 是可执行语句,这意味着函数直到被调用前,都是不存在的。当程序调用函数时,def 语句才会创建一个新的函数对象,并赋予其名字。

  • 主程序调用函数时,必须保证这个函数此前已经定义过。
  • 在函数内部调用其他函数,函数间哪个声明在前、哪个在后就无所谓,因为 def 是可执行语句,函数在调用之前都不存在。

闭包

1. 函数作为变量

def fun1(x):
	print(x)

fun2 = fun1
fun2('abc')

2. 函数作为函数的参数:实参高阶函数

def fun1(x):
	return x

def fun2(fun1, x):
	print(fun1(x))

fun2(fun1, 'abc')

3. 函数中定义函数:嵌套函数

意义:

  • 保证内部函数的隐私。
    内部函数只能被所在的外部函数所调用和访问,不会暴露在全局作用域。
  • 函数开头需要做一些额外工作,而你又需要多次调用这个函数时,将那些额外工作的代码放在外部函数,就可以减少多次调用导致的不必要的开销,提高程序的运行效率。
def fun1():
	def fun2(x):
		return x
	print(fun2('abc'))

fun1()

内部函数可以访问外部函数的变量,但要修改要加nonlocal

def fun1():
	x = 'abc'
	def fun2():
		nonlocal x		# 指定x为外部变量,而不是内部的局部变量
		x = 'def'
	fun2()
	print(x)

fun1()

4. 函数的返回值为函数对象:返回值高阶函数

def fun1():
	return fun2

def fun2(x):
	print(x)

y = fun1()
y('abc')

闭包

闭包 = 函数嵌套 + 返回值高阶函数 + 函数变量(可选)
闭包常和装饰器一起使用

# 闭包
def fun1():
	def fun2(x):	# 函数嵌套
		print(x)
	return fun2		# 返回值高阶函数

y = fun1()	#  函数变量:y=fun2
y('abc')

参数

值传递 和 引用传递

值传递:拷贝参数的值,然后传递给函数里的新变量。原变量和新变量之间互相独立,互不影响。
引用传递:原变量和新变量就会指向同一块内存地址

Python 中的参数传递只是让新变量与原变量指向相同的对象而已,并不存在值传递或是引用传递一说。

def fun(a):
	a = 2

b = 1
fun(b)		# b 和 a 都指向对象:1

参数为任何数据类型:

  • 不可变对象:不会更改原变量
  • 可变对象: 会永久性修改原变量
def fun1(li):
	li.append(4)

def fun2(d):
	d['a'] = 10

# 参数为list、dict
li= [1, 2, 3]
fun1(li)        		# 永久性修改原list
print(li)		# [1, 2, 3, 4]
fun1(li[:])     		# 传递副本,不修改原list
print(li)		# [1, 2, 3]

d = {'a': 1, 'b': 2}
fun2(d)        			 # 永久性修改原来dict
print(li)		# {'a': 10, 'b': 2}

位置参数、关键字参数

位置参数:实参和形参位置顺序一致,一 一对应
关键字参数:无关顺序,需带关键字

def fun(x, y, z=0):      
    pass

# 位置实参
fun(1, 2)
fun(1, 2, 3)

# 关键字实参
fun(y=2, x=1)
fun(y=2, z=3, x=1)

5种参数类型 及 匹配顺序

  • 关键字参数
  • 位置参数
  • 默认值参数:关键字 / 位置,等号两边不要有空格
  • 任意数量的位置参数(*args:空tuple)
  • 任意数量的关键字参数(**kwargs:空dist)

关于实形参的匹配顺序,满足以下原则:

  • 非默认值参数 --> 默认值参数
  • 位置参数 --> *args
  • 关键字参数 --> **kwargs
  • 位置参数 --> 关键字参数
  • *args --> **kwargs
  • *args --> 默认值位置参数
  • 默认值关键字参数 --> **kwargs

关于顺序,只需要记住一个特例:fun(a, b, *args, c=None, kwa, kwb, kwc=None, **kwargs)
a、b、args、c为位置参数,kwa、kwb、kwc、kwargs为关键字参数

所有参数类型的匹配情况

# 位置参数
def func1(a, b, *args, c=None):
    # 默认值参数和*args同时出现:*args --> 默认值参数,且必须将默认值参数转为关键字参数
    print('---func1------------')
    print(a)
    print(b)
    print(c)
    print(args)

func1('a', 'b', 1, 2, 3, c='c')
func1('a', 'b', 1, 2, 3)



# 关键字参数
def func2(kwa, kwb,  kwc=None, **kwargs):
    print('---func2------------')
    print(kwa)
    print(kwb)
    print(kwc)
    print(kwargs)

func2(kwa='kwa', kwb='kwb', kwargs1=1, kwargs2=2)
func2(kwa='kwa', kwb='kwb', kwc='kwc', kwargs1=1, kwargs2=2)



# 位置参数和关键字参数
def func3(a, b, kwa, kwb):
    print('---func3------------')
    print(a)
    print(b)
    print(kwa)
    print(kwb)

func3('a', 'b', kwa='kwa', kwb='kwb')



# *args 和 **kwargs
def func4(*args, **kwargs):
    print('---func4------------')
    print(args)
    print(kwargs)

func4(1, 2, 3, kwargs1=1, kwargs2=2)



# 位置参数和关键字参数
def func5(a, b, *args, kwa, kwb,  **kwargs):
    print('---func5------------')
    print(a)
    print(b)
    print(args)
    print(kwa)
    print(kwb)
    print(kwargs)

func5('a', 'b', 1, 2, 3, kwa='kwa', kwb='kwb', kwargs1=1, kwargs2=2)



# 位置参数和关键字参数
def func6(a, b, *args, c=None, kwa, kwb, kwc=None, **kwargs):
    print('---func6------------')
    print(a)
    print(b)
    print(c)
    print(args)
    print(kwa)
    print(kwb)
    print(kwc)
    print(kwargs)

func6('a', 'b', 1, 2, 3, c='c', kwa='kwa', kwb='kwb', kwc='kwc', kwargs1=1, kwargs2=2)
func6('a', 'b', 1, 2, 3, kwa='kwa', kwb='kwb', kwargs1=1, kwargs2=2)

匿名函数 lambda

减少代码的复杂度

定义、举例

定义:

lambda argument1, argument2,... argumentN : expression

举例:

fun = lambda: print('abc')
fun()

fun = lambda x: x**2
print(fun(3))			# 9

fun = lambda x1, x2: x1+x2
print(fun(1,2))			# 3



# 用于列表内部
li = [(lambda y: y+1)(x) for x in range(10)]
print(li)		# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]



# 作为函数的参数
li = [(1, 20), (3, 0), (9, 10), (2, -1)]
li.sort(key=lambda x: x[1])   # 按列表中元组的第二个元素排序
print(li)			# [(2, -1), (3, 0), (9, 10), (1, 20)]



# 结合 map()、filter()、reduce()
li = [1,2,3,4]
mp = map(lambda x:x**2, li)
for x in mp:
    print(x)

li = range(10)
f = filter(lambda x: x%2==0, li)		# 偶数
for x in f:
	print(x)		# [0,2,4,6,8]


from functools import reduce		# python 3 取消了reduce内置函数

r = range(10)
result = reduce(lambda x,y: x+y, r)		# 求和
print(result)				# 45

lambda 和常规函数 def 的区别

lambdadef
设计意义一行的简单表达式多行语句
只调用一次多次调用,减少代码重复性
专注于简单的任务更复杂的多行逻辑
其它无函数名
可用于列表内部
可作为函数参数

表达式:运算符和操作数所构成的序列。如,x+1,1
语句:执行特定操作。如,x=x+1,x=1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值