Python学习笔记 函数

目录

  简单函数
  匿名函数(lambda表达式)
  嵌套函数
  返回函数和闭包
  高阶函数
  偏函数
  函数的装饰器

简单函数

  所谓函数,就是一种可重复使用的,用来实现单一或相关联功能的代码段。在程序中,我们将一些常用的功能写成一个函数,不仅提高了程序的模块性,还能大大提高代码的重复利用率,这样我们就可以少敲很多代码了~话不多说,入正题

  定义一个函数需要满足以下要求:
    1. 函数代码块以 def 关键字开头,后接函数名圆括号和冒号。
    2. 函数名需要满足变量命名规则,参数需要在圆括号内定义,可以定义任意多个。
    3. 函数的内容必须缩进,并以 return 语句或缩进结束作为函数内容的结束
    4. 以下不是要求,而是说明
    5. return 语句可以在函数结束时返回给调用方一个或多个对象,该对象可以是整型,可以是字符串,也可以是
  函数。总之只要是对象就可以返回。刚才忘了说Python中一切皆为对象!
    6. Python 中的函数总会有返回值。当函数没有指定返回对象,如没有 return 语句或只有一个 return ,则函
  数会返回 None
    7. 函数的调用方法是函数名加圆括号,如果函数有参数,则圆括号内需要有实参

  来个实例:

def func1(arg1, arg2):
# 定义一个名为 func1 的函数,并定义此函数有两个参数 arg1, agr2
    mysum = arg1 + arg2
    # 函数功能实现 。计算 arg1, agr2 的和,并将结果赋值给 mysum
    return mysum
    # 函数返回语句。将 mysum 的值返回
mysum = func1(2, 3)
# 函数调用。调用 func1 函数,并将函数的执行结果赋值给 mysum 。实参(2, 3)依次赋值给形参 arg1, arg2
print(mysum)
# 输出 mysum
# 5

  来个返回多个对象实例:

def func2(long, wide):
# 本函数的功能是计算并返回周长和面积
    myperimeter = (long + wide) * 2
    myarea = long * wide
    return myperimeter,myarea
    # 返回多个对象
# 在接收返回值时,可以用一个变量或与返回个数相同的变量数来接受
myperimeter,myarea = func2(2, 3)
# 用两个变量来接受
print(myperimeter,myarea)
panda = func2(2, 3)
# 用一个变量接收多个返回值,则返回值会自动打包成一个元组赋值给变量
print(panda)
# 10 6
# (10,6)

匿名函数(lambda表达式)

  Python中的匿名函数其实就是 lambda 表达式(变量 = lambda 参数 :函数体),当你不想给函数起名字时,就可以定义一个匿名函数。但匿名函数有一个限制,就是只能有一个表达式,所以它只能实现一些简单的功能。它不用写return 语句,表达式的结果就是返回值(返回值是一个函数对象)。虽然只有一个表达式,但匿名函数也可以有多个参数(也可以有默认参数、关键字参数等参数类型)。下面就来看一下示例

func3 = lambda arg1, arg2 : arg1 * arg2
# 定义匿名函数,并将其返回值赋值给func3
print(func3(3, 4))
# 匿名函数的调用方法与普通函数一样
# 12

  匿名函数常用的一点是作为高阶函数的参数来使用

# 例如下 求字典的最大值
dic = {'arg1': 19, 'arg2': 12, 'arg3': 20}
ret = max(dic, key = lambda i: dic[i])
print(ret)
# arg3

嵌套函数

  顾名思义,嵌套函数即在函数内部定义了一个或多个函数。我们可以把嵌入其内的函数称为内嵌函数,把被嵌套的函数称为外层函数。需要注意的是内嵌函数的作用于只在外层函数的内部,即只有在外层函数内才能调用内嵌函数。

# 例如下
def fun4(arg1):
    print("我是外层函数fun4")
    def fun4_1(arg2):
        print("我是内嵌函数fun4_1,我只能在外层函数fun4内部被调用")
        return arg1 + arg2
    return fun4_1(2)
    # 返回内嵌函数的调用结果
print(fun4(1))
# 输出fun4的调用结果
# fun4_1() #如果在这调用会出现 "NameError" 的异常
# 参数arg1的作用域是整个fun4范围内,所以在fun4_1内可以使用arg1
# 参数arg2的作用域是整个fun4_1范围内,所以并不是整个fun4内都可以使用arg2

返回函数和闭包

  在之前变量类型的笔记里我们说过函数名也可以当做变量使用。既然可以当做变量,那么自然也可以当做另一个函数的返回值。我们把返回值是一个函数的函数叫做返回值函数。因为被返回的函数需要在函数内定义,所以返回函数往往也是一种嵌套函数,区别之处就在于函数的返回值不同。

 # 例如下
def fun5(arg1):
    def fun5_1(arg2):
        return arg1 + arg2
    return fun5_1
    # 把内嵌函数fun5_1返回
mysum = fun5(4)
# 此时的 mysum 就相当于 fun5_1 函数
print(mysum(5))
# 9
# 第一次调用fun5时并没有执行fun5_1函数,而是把fun5_1作为返回值赋值给mysum
# 若想执行fun5_1函数就必须调用 mysum 。事实上这也是提供了一种在外部函数之外调用内嵌函数的方法

  闭包:定义一个闭包要满足一下几点:

    1. 必须是嵌套函数
    2. 内嵌函数必须引用了定义在闭合范围内(外部函数里)的变量
    3. 外部函数必须返回内嵌函数——必须返回那个内部函数

  事实上我上面的那个例子就是一个典型的闭包,闭包在第一次调用时不会执行内嵌函数,而是把内嵌函数最返回值返回给调用方。在这个过程中,内嵌函数会保存外部函数中所定义的变量,如上例的arg1(其实是保存内嵌函数之前所有的变量)。不过也仅仅是保存起来,并不能直接在内嵌函数内对外部函数的变量进行重新赋值,当需要进行对外部变量的重新赋值时,需要加关键字 nonlocal 进行声明。下面来个例子

def fun5(arg1):
    arg1_1 = 10
    def fun5_1(arg2):
        # arg1_1 += 10 这种直接对其修改,会报错
        nonlocal arg1_1
        arg1_1 += 10
        print(arg1_1)
        return arg1 + arg2 + arg1_1
    return fun5_1
mysum = fun5(4) # 每一次调用 fun5 都会返回不同的函数
# 此时,fun5_1 函数已经保存了fun5 中相关的变量了
print(mysum(5))
# 20
# 29

  需要注意的是返回闭包时,返回函数不能引用任何循环变量,否则就会出错

# 例如下
def fun6():
    L = []
    for i in range(1,4):
        def fun6_1():
            return i*i
        L.append(fun6_1) #分别把保存了i= 1,2,3时的fun6_1函数插入到列表里
    return L
fun6_2, fun6_3, fun6_4, = fun6() # 取出分别保存了i=1,i=2,i=3 的fun6_1函数
print(fun6_2(), fun6_3(),fun6_4())
# 我们想要输出的是: 1 4 9
# 但现实是输出的是: 9 9 9

############################改进方法############################
def fun7():
    def fun7_1(j):
        def fun7_1_1():
            return j*j
        return fun7_1_1
    L = []
    for i in range(1,4):
        L.append(fun7_1(i))
    return L
fun7_2, fun7_3, fun7_4, = fun7()
print(fun7_2(), fun7_3(),fun7_4())

高阶函数

  Python中把一些以函数为实参传入的特殊函数称为高阶函数。它的标准库里提供了很多的高阶函数,下面我们来介绍几个常用的高阶函数

  map函数
    map函数的原型是map(func, *iterables),其中第一个参数 func 是一个函数,第二个参数是一个可迭代对
  象。map函数的功能是把函数 func 依次作用到迭代对象 iterables 的每一个元素上,然后返回新的可迭代对象(事
   实上是一个 map类型的可迭代对象)。简单来说,如果你想对序列的每一个元素都进行相同的操作,那么就可以
  用到 map 函数(听起来用循环也可以实现相同的效果是吧)。

# 例如下
def fun8(arg):
    return arg*arg
L = [1, 2, 3, 4, 5]
L2 = map(fun8, L)
L3 = map(lambda n : n * n, L)
# 第一个参数也可以是lambda表达式
print(list(L2))
print(list(L3))
# [1, 4, 9, 16, 25]
# [1, 4, 9, 16, 25]

  reduce函数
    reduce函数的原型是reduce(function, sequence[, initial]),其中第一个参数是一个函数,第二个参数是一个
  可迭代对象。需要注意的是reduce函数对其第一个参数有一定要求,即function必须是一个有两个参数且有返回值
  的函数reduce函数的功能是对一个可迭代对象按照 function 函数的规则计算,合并成一个结果并返回。

# 例如下
from functools import reduce
# 要用这个函数必须导入相应的模块
def fun9(arg1, arg2):
    return arg1 + arg2
L = [1, 2, 3, 4, 5]
mysum = reduce(fun9, L)
print(mysum)
# 15

  filter函数
    filter函数的原型是filter(function or None, iterable),其中第一个参数是一个函数或者是 None,第二个参
  数是一个可迭代对象。filter函数的功能是对一个可迭代对象按照 function 函数定义的规则进行过滤,将符合条件
  的元素生成一个新的可迭代对象并返回,(返回值是一个filter类型的可迭代对象)。如果第一个参数是函数,则要求该
  函数的返回值必须是布尔值。如果是None,则返回原序列。

# 例如下
def fun10(arg1):
    return (arg1 % 2) != 0
# 把偶数过滤掉
L = [1, 2, 3, 4, 5]
newL1 = filter(fun10, L)
newL2 = filter(None, L)
print(list(newL1))
print(list(newL2))
# [1, 3, 5]xcd
# [1, 2, 3, 4, 5]

  sorted函数
    sorted函数的原型是sorted(__iterable, key, reverse)。它的第一个参数表示一个可迭代对象,第二个参数可
   以是一个函数也可以是 None(默认值),第三个参数是一个布尔值(默认为False)。sorted的功能是对一个序列以key
  函数为逻辑 (规则) 进行升序或降序排序可以这么理解:先是把key函数作用于序列L1的每一个元素,这样就产生了
  一个新的序列L2,可以把这两个序列看成一个以L1元素为键,对应L2元素为键值的一个字典。然后对字典以键值为
  关键字进行排序,最后返回字典的值组成的序列当参数reverse为默认值False时,进行升序排;为True时进行降
  序排。

# 例如下
L = [-4, 1, -2, 5, 3, -6]
newL1 = sorted(L, key = abs)
# 对列表L的元素按绝对值进行升序排序
newL2 = sorted(L, key = abs, reverse = True)
# 对列表L的元素按绝对值进行降序排序
print(newL1)
print(newL2)
# [1, -2, 3, -4, 5, -6]
# [-6, 5, -4, 3, -2, 1]

偏函数

  我们都知道int()函数的用法,它的功能是把表示某种进制数的字符串转化为十进制数,但默认字符串表示的是十进制数。也就是说我要把表示二进制的字符串转化为十进制数就要这样写a = int("101", 2)。那如果我的工程里面要多次把表示二进制的字符串转化为十进制数,而我又很懒,不想一直传进两个参数,那我该怎么办?我可以用偏函数来搞定。
  偏函数是一种某些参数值被固定了的函数,相当于一个由特定参数的函数。定义偏函数需要用到高阶函数 partial。partial 函数的作用就是固定其他函数的某些参数值,并返回一个新的函数。

# 例如下
from functools import partial
# 导入高阶函数 partial
int2 = partial(int, base = 2)
# 利用partial定义偏函数,此时的int2就是一个偏函数
print(int("101",2))
print(int2("101"))
# 可以发现,定义了偏函数之后,我就可以少传进一个参数了
# 5
# 5

函数的装饰器

  装饰器分为类装饰器和函数装饰器等,装饰器的作用是在不改动源代码的基础上进行功能扩展。
  函数的装饰器本质上就是一种返回函数的高阶函数,它可以在不改动原函数代码的情况下无限制的扩展函数的功能,它的定义需要用到返回函数和闭包结构。
  要创建装饰器需要知道以下几点:
    1. 装饰器是一个函数。
    2. 装饰器取被装饰函数为参数。 即,需要把被修饰函数作为参数传入装饰器
    3. 装饰器返回一个新函数。这个新函数的功能包括被装饰函数的功能和装饰器的功能
    4.装饰器维护被装饰函数的签名。(函数参数的个数和类型称为其签名)即装饰器要确保它返回的函数与被装
   饰器函数有同样的参数(指个数和类型都相同)

   函数的装饰器分为不带参和带参两种,下面将分别介绍。

   不带参装饰器

def fun11(func):
    def fun11_1(*args, **kwargs):
    # 为什么写*args和**kwargs这两个参数?因为要满足上面第4print("这是装饰器,在执行被装饰的函数前都要先执行我")
        return func(*args, **kwargs)
    return fun11_1
    # 上面的结构实际上就是一个闭包结构
@fun11    # 装饰器,即 @ + 装饰器的名字
def fun12(*args, **kwargs):
    print("这是功能被扩展的函数")
# 紧接着装饰器定义新的函数,这个函数就是功能被扩展的函数,它将拥有装饰器的所有功能
fun12()

# 输出如下:
# 这是装饰器,在执行被装饰的函数前都要先执行我
# 这是功能被扩展的函数

#########################另外一种装饰方法#########################
'''
def fun11(func):
    def fun11_1(*args, **kwargs):
        print("这是装饰器,在执行被装饰的函数前都要先执行我")
        return func(*args, **kwargs)
    return fun11_1
def fun12(*args, **kwargs):
    print("这是功能被扩展的函数")
fun13 = fun11(fun12)
fun13()
# fun13也将同时拥有fun11和fun12的所有功能
'''

   带参的装饰器

def fun14(name, hobby):
# 带参数的装饰器需要多写一层函数,不可以直接在fun14_1里传进其他参数
    def fun14_1(func):
        def fun14_1_1(*args, **kwargs):
            print("这是{0}的装饰器{1}".format(name, hobby))
            return func(*args, **kwargs)
        return fun14_1_1
        # 返回内嵌函数
    return fun14_1
    # 返回内嵌函数
@fun14("阿珍", "阿强")
def fun15(*args, **kwargs):
    print("这是阿珍")
fun15()

# 问:装饰器是怎么工作的(以上代码为例)?
# 答:1、执行 fun14(name, hobby),并返回 fun14_1。如果装饰器无参数,此步骤省略
#     2、执行 fun14_1(fun15),并返回 fun14_1_1。
#     3、执行 fun15 = fun14_1_1

   为了避免出现不必要的麻烦(书上说什么函数有可能会忘记自己的身份,很复杂,涉及到Python内部的知识),我们写自己的装饰器时一定要导入 functools 模块,并调用wraps函数(这也是一个装饰器)。具体如下

from functools import wraps
def fun11(func):
    @wraps(func)
    # 调用wraps函数
    def fun11_1(*args, **kwargs):
        print("这是装饰器,在执行被装饰的函数前都要先执行我")
        return func(*args, **kwargs)
    return fun11_1
@fun11
def fun12(*args, **kwargs):
    print("这是被扩展的功能函数")
fun12()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python学习笔记PDF是一种学习Python编程语言的资料形式,它包含了Python的基本语法、数据类型、流程控制、函数、模块、面向对象编程、异常处理等相关内容。以下是关于Python学习笔记PDF的详细内容说明: 1. 基本语法:Python学习笔记PDF中,首先介绍了Python的基本语法,例如如何定义变量、数据类型的使用(包括整数、浮点数、字符串、列表、元组、字典等),以及如何进行算术运算、比较运算和逻辑运算。 2. 流程控制:Python学习笔记PDF中,进一步介绍了流程控制的知识,包括条件判断和循环控制。条件判断主要是通过if语句进行判断执行不同的代码块,而循环控制则通过while循环和for循环来实现重复执行一段代码。 3. 函数Python学习笔记PDF中,对函数的概念和使用进行了详细的解释。函数是代码的封装和组织方式,通过定义函数可以提高代码的重用性和可读性。学习者将了解到如何定义函数、调用函数函数参数的传递以及函数返回值的使用。 4. 模块:Python学习笔记PDF中,介绍了Python中的模块和包的概念。模块是一组函数、类或变量的集合,以.py文件的形式存在,可以被其他程序调用和使用。学习者将学习如何导入模块、使用模块中的函数和变量。 5. 面向对象编程:Python学习笔记PDF中,对面向对象编程进行了系统的讲解。面向对象编程是一种以对象为基本单位的编程思想,通过定义类和对象,可以更好地组织和管理代码。学习者将了解如何定义类、创建对象、封装、继承和多态的使用。 6. 异常处理:Python学习笔记PDF中,对异常处理进行了介绍。异常是程序在运行过程中出现的错误,通过捕获和处理异常,可以更好地控制程序的执行流程并提高程序的健壮性。学习者将了解到如何使用try-except语句来捕获和处理异常。 总之,Python学习笔记PDF是一份全面而详细的学习Python编程语言的资料,通过学习该资料,学习者将获得扎实的Python编程基础,并能够运用Python进行简单的程序开发。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值