Task06 函数与Lambda表达式

在这里插入图片描述

函数

定义

  • 创建函数用def语句,其格式为:def fun_name(par1,par2,…): 由def关键字,函数名和参数表组成
def 函数名(参数):
    函数体
  • 任何传入参数或者自变量必须放在圆括号中间
  • 定义函数内容以冒号开始,注意缩进问题
  • def 语句创建函数时,可以用 return 语句指定应该返回的值,该返回值可以是任意类型。需要注意的是,return 语句在同一函数中可以出现多次,但只要有一个得到执行,就会直接结束函数的执行。
  • 不带表达式的return相当于返回None。
def printme(str):
    print(str)
printme("我要调用用户自定义函数!")  # 我要调用用户自定义函数!
printme("再次调用同一函数")  # 再次调用同一函数
temp = printme('hello') # hello
print(temp)  # None
我要调用用户自定义函数!
再次调用同一函数
hello
None

函数参数

  • 函数定义过程传的是形参,调用过程传的是实参

python中的函数参数主要有3种形式:

  • 位置或关键字参数
    位置或关键字参数是python默认的参数类型,函数的参数定义为该类参数后,可以通过位置参数,或者关键字参数的形式传递参数
    **注意:**函数参数列表中可以定义默认参数,但是python不允许带默认值的参数定义在没有默认值参数之前

  • 任意数量的位置参数
    任意数量的位置参数在定义的时候需要一个星号前缀来表示,在传递参数的时候,可以在原有参数的后面添加0个或多个位置参数,这些参数将会被放在 元组内并传入函数。
    **注意:**任意的位置参数(一个 一个星号前缀)必须定义在位置或关键字参数之后,并且在任意数量的关键字参数(两个星号前缀)之前

  • 任意数量的关键字参数
    任意数量的关键字参数在定义时,参数名称之前需要两个星号作为前缀,
    这样定义出来的参数可以在原有参数后面添加任意个0个或多个关键字参数

函数文档

使用函数文档帮助更好理解函数作用

  • 在函数开头写下字符串,其不被打印出来,但作为函数的一部分保存起来了。称作函数的文档字符串
  • 函数的文档字符串通过__doc__获取
  • 用help()查看文档
def MyFirstFunction(name):
    "函数定义过程中name是形参"
    print('传递进来的{0}叫做实参,因为Ta是具体的参数值!'.format(name))
MyFirstFunction('老马的程序人生')  
print(MyFirstFunction.__doc__)  
help(MyFirstFunction)
# Help on function MyFirstFunction in module __main__:
# MyFirstFunction(name)
# 函数定义过程中name是形参
传递进来的老马的程序人生叫做实参,因为Ta是具体的参数值!
函数定义过程中name是形参
Help on function MyFirstFunction in module __main__:

MyFirstFunction(name)
    函数定义过程中name是形参

变量作用域

  • Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
  • 定义在函数内部的变量拥有局部作用域,该变量称为局部变量。
  • 定义在函数外部的变量拥有全局作用域,该变量称为全局变量。
  • 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。

当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了:

内嵌函数

函数定义允许在函数内部创建另一个函数,这种函数称作内嵌函数

def outer():
    print('outer函数在这被调用')

    def inner():
        print('inner函数在这被调用')

    inner()  # 该函数只能在outer函数内部被调用


outer()
outer函数在这被调用
inner函数在这被调用

闭包

  • 是函数式编程的一个重要的语法结构,是一种特殊的内嵌函数。

  • 如果在一个内部函数里对外层非全局作用域的变量进行引用,那么内部函数就被认为是闭包。

  • 通过闭包可以访问外层非全局作用域的变量,这个作用域称为 闭包作用域。

  • 使用闭包时注意:闭包的概念就是由内部函数而来的所以不能在外部函数以外引用内部函数。

  • 在闭包中,外部函数的局部变量对应内部函数的局部变量,类似于全局变量与局部变量的关系,
    但在内部函数中只能对外部函数的局部变量进行引用而不能进行改变,例子如下:

def funx():
    x=5
    def funy():
        x *= x
        return(x)
    return funy()
print(funx())
---------------------------------------------------------------------------

UnboundLocalError                         Traceback (most recent call last)

<ipython-input-13-8506de71b60e> in <module>()
      5         return(x)
      6     return funy()
----> 7 print(funx())


<ipython-input-13-8506de71b60e> in funx()
      4         x *= x
      5         return(x)
----> 6     return funy()
      7 print(funx())


<ipython-input-13-8506de71b60e> in funy()
      2     x=5
      3     def funy():
----> 4         x *= x
      5         return(x)
      6     return funy()


UnboundLocalError: local variable 'x' referenced before assignment

python认为内部函数的x是局部变量时,外部函数的x就被屏蔽了起来,所以执行x*=x时候,在右边就找不到局部变量x的值,因此报错.

解决方法:

  • 间接使用容器类型来存放,因为容器类型不是放在栈里,所以当栈消失时不会消失。
def funx():
    x=[5]
    def funy():
        x[0] *= x[0]
        return x[0]
    return funy()
print(funx())
25
  • 内部函数修改外部函数里的局部变量使用nonlocal关键字,使用方法与global一样
def funx():
    x=5
    def funy():
        nonlocal x
        x *= x
        return(x)
    return funy()
print(funx())#25
25

递归函数

简单来说就是函数调用自身

  • 设置递归的层数,Python默认递归层数为 100
import sys
sys.setrecursionlimit(层数)

lambad表达式

定义

python语句允许使用lambad语句创建匿名函数,也就是说函数没有具体名称;
lambad语句中,冒号前是函数参数,若由多个函数使用逗号分隔,冒号右边是返回值
语法如下:

 lambda 参数:返回值

例子:

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

使用lambad函数注意以下4点:

  • lambad定义的是单行函数,如果需要复杂的函数,应该使用def语句
  • lambad参数列表可以包含多个参数
  • lambad语句有且只有一个返回值
  • lambad语句中的表达式不能含有命令,而且限有一条表达式

匿名函数的应用

匿名函数 常常应用于函数式编程的高阶函数 (high-order function)中,主要有两种形式:

  • 参数是函数 (filter, map)
  • 返回值是函数 (closure)

eg01

  • 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, 3, 5, 7, 9]
  • map(function, *iterables) 根据提供的函数对指定序列做映射。
m1 = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
print(list(m1))  
# [1, 4, 9, 16, 25]

m2 = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
print(list(m2))  
# [3, 7, 11, 15, 19]
[1, 4, 9, 16, 25]
[3, 7, 11, 15, 19]

练习题:

1.怎么给函数编写⽂档?

在定义函数的首行写一个字符串,可通过调取__doc__查看,通过help()查看文档。

2.怎么给函数参数和返回值注解?

在参数后面加 :;在:后加数据类型。在 def 的括号后面箭头说明返回值类型

def func(x: int, y: int) -> int:

3.闭包中,怎么对数字、字符串、元组等不可变元素更新。

需要使用 nonlocal 关键字。

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

a = [[6, 5], [3, 7], [2, 8]]
print(a)
a = sorted(a, key=lambda x: x[0], reverse=False)
print(a)
a = sorted(a, key=lambda x: x[1], reverse=False)
print(a)
[[6, 5], [3, 7], [2, 8]]
[[2, 8], [3, 7], [6, 5]]
[[6, 5], [3, 7], [2, 8]]

5.利用python解决汉诺塔问题?
有a、b、c三根柱子,在a柱子上从下往上按照大小顺序摞着64片圆盘,把圆盘从下面开始按大小顺序重新摆放在c柱子上,尝试用函数来模拟解决的过程。(提示:将问题简化为已经成功地将a柱上面的63个盘子移到了b柱)

def move(n,a,b,c):
    if n == 1:
        print(a, "->", c)
    else:
        move(n-1, a, c, b)
        move(1, a, b, c)
        move(n-1, b, a, c)
move(64, 'a', 'b', 'c')
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页