Python基础之函数与Lambda表达式

DataWhale-Python基础-10.函数与lambda表达式

1.函数

1.1函数的定义

  • 函数以def关键词开头,后接函数名和圆括号()。

  • 函数执行的代码以冒号起始,并且缩进。

  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回None。

      def functionname(parameters):
          "函数_文档字符串"
          function_suite
          return [expression]
    

1.2函数的调用

#例子
def add(a, b):
    print(a + b)


add(1, 2)  # 3
add([1, 2, 3], [4, 5, 6]) # [1, 2, 3, 4, 5, 6]

1.3函数文档

def Fisrtfunction(name):
    "函数的定义过程中name是形参"
    #因为name只是一个形式,表示占据一个参数的位置
    print("传进来的{0}叫做实参,因为它才是具体的数值".format(name))
    
Fisrtfunction('Wine')
# 传进来的Wine叫做实参,因为它才是具体的数值
print(Fisrtfunction.__doc__)
# 函数的定义过程中name是形参
help(Fisrtfunction)
#Help on function Fisrtfunction in module __main__:

#Fisrtfunction(name)
#    函数的定义过程中name是形参

1.4函数参数

  • 位置参数

  • 默认参数

  • 可变参数

  • 关键字参数

  • 命名关键字参数

  • 参数组合

      def functionname(arg1, arg2=v, *args, *, nkw, **kw):
          "函数_文档字符串"
          function_suite
          return [expression]
    
  • arg1 -位置参数,这些参数在调用时位置固定

  • arg2 = v -默认参数=默认值,调用时若没有传入默认参数,则默认参数取默认值

  • arg -可变参数,可以是0到任意个,自动组装成元组;加了的变量名会存放所有未命名的变量参数。

  • **kw -关键字参数,可以是0到任意个,自动组装成字典

  • *,nkw -命名关键字参数,用户想要输入的关键字参数,定义方式是nkw前面+一个分隔符,如果需要限制关键字参数的名字,就可以用命名关键字参数;在使用命名关键字参数时,要特别注意不能缺少参数名。

    可变参数和关键字参数的异同:
    1.可变参数允许传入0到多个参数,它们在函数调用时自动组装乘一个元组
    2.关键字参数允许传入0到多个参数,它们在函数内部自动组装成一个字典
    

参数组合
在 Python 中定义函数,可以用位置参数、默认参数、可变参数、命名关键字参数和关键字参数,这 5 种参数中的 4 个都可以一起使用,但是注意,参数定义的顺序必须是:

  • 位置参数、默认参数、可变参数和关键字参数。
  • 位置参数、默认参数、命名关键字参数和关键字参数。
    要注意定义可变参数和关键字参数的语法:
  • *arg是可变参数,args接受的是一个元组
  • **kw是关键字参数,kw接收的是一个字典

命名关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。定义命名关键字参数不要忘了写分隔符 *,否则定义的是位置参数。

警告:虽然可以组合多达 5 种参数,但不要同时使用太多的组合,否则函数很难懂。

1.5函数的返回值

return

#例子
def add1(a,b):
    return a + b
add1(1,2)
# 3

1.6变量作用域

  • Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

  • 定义在函数内部的变量拥有局部作用域,该变量称为局部变量

  • 定义在函数外部的变量拥有全局作用域,该变量称为全局变量

  • 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。

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

#global全局关键字的应用
num = 1
def func1():
    global num
    print(num)
    num = 123
    print(num)
    
func1()
#1
#123

内嵌函数

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

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

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


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

闭包

  • 闭包是函数式编程的一个重要的语法结构,是一种特殊的内嵌函数
  • 如果在一个内部函数里对外层非全局作用域的变量进行引用,那么内部函数就被认为是闭包
  • 通过闭包可以访问外层非全局作用域的变量,这个作用域被称为闭包作用域。
#例子
def funX(x):
    def funY(y):
        return x * y
    return funY
i = funX(8)
print(type(i))
print(i(5))

#闭包的返回值通常是函数
def make_counter(init):
    counter = [init]

    def inc(): counter[0] += 1

    def dec(): counter[0] -= 1

    def get(): return counter[0]

    def reset(): counter[0] = init

    return inc, dec, get, reset


inc, dec, get, reset = make_counter(0) 
#这里的inc,dec,get,reset分别对应make_counter(0)函数对应返回的四个值
inc() #counter[0] += 1
inc() #counter[0] += 1
inc() #counter[0] += 1
print(get())  # 3
dec() #counter[0] -= 1
print(get())  # 2
reset() #counter[0] = init
print(get())  # 0

#如果要修改闭包作用域中的变量则需要 nonlocal 关键字
def outer():
    num = 10
    
    def inner():
        nonlocal num #这里将num变为外部嵌套函数内的变量,即outer函数下的变量
        num = 100
        print(num)
    
    inner()
    print(num)
outer()
# 100
# 100

递归

  • 如果一个函数在内部调用自身本身,这个函数就是递归函数。
# 例1:n! = 1*2*3...*n

# 循环方法
n = 5
for k in range(1,5):
	n *= k
print(n)
# 120

# 递归法
def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n-1)
factorial(5)
# 120

#例2:斐波那契数列
#循环法
i = 0
j = 1
lst = [i,j]
for k in range(2,10):
    m = lst[k-1] + lst[k-2]
    lst.append(m)
print(lst)
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

#递归法
def fib(n):
    if n <= 1:
        return n
    else:
        return fib(n-1) + fib(n-2)
fib(9)
# 34

2.Lambda表达式

2.1匿名函数的定义

在Python中有两类函数:

  • 用def关键字定义的正规函数

  • 用lambda关键字定义的匿名函数
    Python里用lambda来创建匿名函数,语法结构如下:

    lambda argument_list:expression
    
  • lambda - 定义匿名函数的关键字

  • argument - 函数参数,可以是位置参数,默认参数,关键字参数和正规函数里的参数类型一样。

  • : - 冒号,函数参数和表达式之间要加个冒号

  • expression - 一个表达式,输入函数的参数,输出一些值。

  • expression中没有return语句,因为lambda不需要它来返回,表达式本身结果就是返回值。

  • 匿名函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。

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

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

sum2 = lambda *arg:sum(arg)
sum2(1,2,3,4)
# 10

2.2匿名函数的应用

函数式编程是指代码中每一块都是不可变的,都由纯函数的形式组成。这里的纯函数,是指函数本身相互独立、互不影响,对于相同的输入,总会有相同的输出,没有任何副作用。

#非函数式编程
def f(x):
    for i in range(0,len(x)):
        x[i] += 10
        
    return x
x = [1,2,3]
f(x)
#[11,12,13]

#函数式编程
#函数式编程
def f(x):
    y = []
    for item in x:
        y.append(item + 10)
    return y
x = [1,2,3]
f(x)
#[11,12,13]

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

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

如,在 filter和map函数中的应用:

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

除了Python这些内置的函数之外,我们还可以自己定义一些高阶的函数。

def apply_to_list(fun, some_list):
    return fun(some_list)

lst = [1, 2, 3, 4, 5]
print(apply_to_list(sum, lst))
# 15

print(apply_to_list(len, lst))
# 5

print(apply_to_list(lambda x: sum(x) / len(x), lst))
# 3.0

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

help()是Python中内置函数,通过__doc__方法、help()函数可以查询Python中函数的⽤法。
在定义函数时,可以在函数内部编写⽂档字符串,⽂档字符串就是对函数的说明

文档字符串(DocStrings):
用于解释文档程序,帮助你的程序文档更加简单易懂。
在函数体的第一行使用一对三个单引号 或者一对三个双引号来定义文档字符串。
文档字符串使用惯例:它的首行简述函数功能,第二行空行,第三行为函数的具体描述。
可以使用 doc(注意双下划线)\help()函数调用函数中的文档字符串属性。

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

这个也可以在上述的文档里进行注解

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

闭包中我们利用nonlocal关键字来对一些不可变元素进行更新

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

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

5.利用python解决汉诺塔问题?

def hanoi(n,x,y,z):
    if n == 1:
        print(x,"--->",z)
    else:
        hanoi(n-1,x,z,y)
        print(x,"--->",z)
        hanoi(n-1,y,x,z)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值