Python-6-函数与Lambda表达式

函数与lambda表达式

函数

Python中万物皆对象,函数也不例外,python中低阶函数既可以做高阶函数的参数也可以做高阶函数的返回值

函数定义
函数以关键词def开头,后接函数名、小括号()和冒号:
函数以 return [表达式] 结束;若无return语句,则默认返回None;若无表达式,则返回None

def functionname(parameters):
    function_suite
    return [expression]

函数参数
Python函数有多种参数形态,由简到繁为:
位置参数 (positional argument)
默认参数 (default argument)
可变参数 (variable argument)
关键字参数 (keyword argument)
命名关键字参数 (name keyword argument)
参数组合

  1. 位置参数
    位置参数在调用函数 (call function) 时位置要固定
	def functionname(arg1):
    	"函数_文档字符串"
   		function_suite
    	return [expression]
  1. 默认参数
    默认参数在函数调用时已经赋值,调用函数时,默认参数的值如果没有传入,则被认为是默认值;
    默认参数需要放在位置参数之后,不然会报错;
    函数调用时,若指定给形参赋值,则参数顺序可以与函数命名时的顺序不一致,解释器能够用参数名匹配参数值;
	def functionname(arg1, arg2=v):
    	"函数_文档字符串"
    	# arg1是位置参数,arg2是默认参数,v 为默认值
    	function_suite
    	return [expression]
  1. 可变参数
    可变参数是指传入参数的个数不固定,既可以没有,也可以有多个,在函数调用时会自动组合成元组;
    可变参数前要加 *,以和其他参数区分
    可变参数会接收所有未命名的变量参数
	def functionname(arg1, arg2=v, *args):
    	"函数_文档字符串"
    	function_suite
    	return [expression]
  1. 关键字参数
    关键字参数与可变参数相似,都允许传入零到任意个参数,但命名关键字参数接收的是字典
    关键字参数前要加 **,以区分其他参数
	def functionname(arg1, arg2=v, *args, **kw):
    	"函数_文档字符串"
    	function_suite
    	return [expression]
  1. 命名关键词参数
    命名关键字参数用于限制关键字参数的名字,定义格式是 *, nkw;调用的函数要使用命名关键字参数时,不能缺少参数名
	def functionname(arg1, arg2=v, *args, *, nkw, **kw):
    	"函数_文档字符串"
    	function_suite
    	return [expression]
  1. 参数组合
    函数参数定义的顺序只有两种:
    a. 位置参数、默认参数、可变参数和关键字参数。
    b. 位置参数、默认参数、命名关键字参数和关键字参数。

变量作用域
定义在函数内部的变量拥有局部作用域,该变量称为局部变量;定义在函数外部的变量拥有全局作用域,该变量称为全局变量;局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。
当内部作用域想修改外部作用域的变量时,需要global和nonlocal关键字;global关键字在函数或其他局部作用域中使用全局变量,nonlocal关键字在函数或其他作用域中使用外层(非全局)变量

  1. 闭包
    闭包是一种特殊的内嵌函数,如果在一个内部函数里对外层非全局作用域的变量进行引用,那么内部函数就被认为是闭包。
    通过闭包可以访问外层非全局作用域的变量,这个作用域称为闭包作用域;
    闭包的返回值通常是函数;
    修改闭包作用域中的变量需要 nonlocal 关键字;

  2. 递归
    一个函数在内部调用自身本身,这个函数就是递归函数
    递归采用的是一种自上而下的思想,但计算开销大,容易导致栈溢出

lambda表达式

python中的函数可以分为两类:一类是关键字def定义的正规函数;另一类是关键字lambda定义的匿名函数,即没有函数名的函数

匿名函数的定义
语法结构:lambda argument_list: expression
argument_list 是函数参数,可以是位置参数、默认参数、关键字参数,和正规函数里的参数类型一样;
expression 是一个表达式,输入函数参数,输出函数值;不需要 return 语句。
note:匿名函数有自己的命名空间,不能访问自己参数列表之外或全局命名空间里的参数

lbd_sqr = lambda x: x ** 2
print(lbd_sqr)
# <function <lambda> at 0x000000BABB6AC1E0>

y = [lbd_sqr(x) for x in range(10)]
print(y)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

func = lambda *args: sum(args)
print(func(1, 2, 3, 4, 5))  # 15

匿名函数的应用
函数式编程 是指代码中每一块都是不可变的,都由纯函数的形式组成。纯函数是指函数本身相互独立、互不影响,对于相同的输入,总会有相同的输出,没有任何副作用。
匿名函数 常常应用于函数式编程的高阶函数中,主要有两种形式:
参数是函数 (filter, map)
返回值是函数 (闭包,closure)

  1. filter(function, iterable)
    过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,可以使用 list() 转换为列表
	odd = lambda x: x % 2 == 1
	templist = filter(odd, [1, 2, 3, 4, 5, 6, 7, 8, 9])
	print(list(templist))  # [1, 3, 5, 7, 9]
  1. map(function, *iterables)
    根据提供的函数对指定序列做映射
	m = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
	print(list(m1))  
	# [3, 7, 11, 15, 19]

练习题

  1. 怎么给函数编写文档?
    在函数开头添加的字符串即视为文档字符串,表示函数的注释,将作为函数的一部分存储起来,可通过函数的 __doc__ 属性访问

  2. 怎么给函数参数和返回值注解?
    函数参数的注解可以在定义函数时,在参数的后面加上冒号和要求使用的类型 : type;但参数注解不会强制改变传入参数的类型,只能作为提示
    返回值的注解在定义函数的冒号之前,小括号之后添加 ‘->’ 和返回值类型,即 -> type
    这些注解都会以字典的形式存储在函数的 __annotations__ 属性访问

	def accumlate(x:int, y:int) -> int:
    	return x*y
    
    print(accumlate.__annotations__)
	# {'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}
  1. 闭包中,怎么对数字、字符串、元组等不可变元素更新。
    可通过使用关键词nonlocal实现

  2. 分别根据每一行的首元素和尾元素大小对二维列表 a = [[6, 5], [3, 7], [2, 8]] 排序。(利用lambda表达式)

	a = [[6, 5], [3, 7], [2, 8]]
	b = sorted(a, key=lambda x: x[0])
	c = sorted(a, key=lambda x: x[-1])
  1. 利用python解决汉诺塔问题?
    汉诺塔
class Solution:
    def hanota(self, A: List[int], B: List[int], C: List[int]) -> None:
        n = len(A)
        self.move(n, A, B, C)
    # 定义 move 函数移动汉诺塔
    def move(self,n, A, B, C):
        if n == 1:
            C.append(A[-1])
            A.pop()
            return 
        else:
            self.move(n-1, A, C, B)  # 将A上面n-1个通过C移到B
            C.append(A[-1])          # 将A最后一个移到C
            A.pop()                  # 这时,A空了
            self.move(n-1,B, A, C)   # 将B上面n-1个通过空的A移到C
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值