python-learning-note-3

Posted on May 15, 2023

函数

函数也是一个对象,用来保存一些可执行的代码

在定义函数时,可以在函数名后的()中定义数量不等形参:相当于在函数内部声明了变量,但不赋值。定义形参时,可以指定默认值,在用户没有传递参数时起作用。

如果在函数定义时指定了实参,在调用时也必须传递实参。

实参的传递方式:

  • 位置参数:将对应位置的实参复制给对应位置的形参
  • 关键字参数:可以不按照形参定义的顺序去传递,而直接根据参数名去传输参数 典例:print(‘hello’, end=’’)

位置参数与关键字参数可以混用,位置参数必须写到前面

函数在调用时,解析器不会检查实参的类型,实参可以传递任意类型的对象

在函数中对形参进行重新赋值,不会影响其他变量;如果形参执行的是一个对象,当通过形参修改对象时,会影响到所有指向该对象的变量

不定长参数

在定义函数时,在形参前加*,形参将会获取到所有的实参,将它们保存到一个元组中(与元组中用法相同)

可变参数不是必须写在最后,注意带*后的所有参数,必须以关键字参数的形式传递;如果在形参的开头直接写一个*,则要求所有的参数必须以关键字参数的形式传递

def fn(*,a,b,c)

*形参只能接收位置参数,不能接收关键字参数

**形参可以接收其他关键字参数,它会将这些参数统一保存到一个字典中,字典的key是参数名字,value是参数的值;**参数只能有一个,并且必须写在所有参数的最后

传递实参时,也可以在序列类型的参数前添加星号,这样会将序列中的元素依次作为参数传递,这里要求序列元素个数与形参一致

def fn(a,b,c):
    print('a =',a)
    print('b =',b)
    print('c =',c)

t = (10,20,30)
d = {'a':10,'b':20,'c':30}
fn(*t) # 对tuple进行解包(拆包)
fn(**d) # 对dict进行解包(拆包)

返回值

就是一般的return用法

文档字符串

help()是Python中内置的函数,可以用来查询python中函数的用法

在定义函数时,可以在函数内部编写文档字符串,文档字符串就是函数的说明

作用域与命名空间

作用域就是经典的局部变量与全部变量,在函数内部修改全局变量用global声明

命名空间指变量存储的位置,每一个变量都需要存储到指定的命名空间中,每一个作用域都有一个它对应的命名空间

全局命名空间,用来保存全局变量。函数命名空间用来保存函数中的变量,命名空间实际上就是一个字典,是一个专门用来存储变量的字典

locals()用来获取当前作用域的命名空间,返回值为一个字典;globals() 函数可以用来在任意位置获取全局命名空间,可以修改value但不建议

递归

递归式函数,在函数中自己调用自己,递归函数的思想:将一个大问题分解为一个个小问题,直到问题无法分解时,再去解决问题

递归式函数的两个条件:

  • 基线条件:问题可以被分解为最小问题,当满足基线条件时,递归就不在执行了
  • 递归条件:将问题继续分解的条件

高阶函数

在Python中,函数是一等对象:

  • 对象是运行时创建的
  • 能赋值给变量或作为数据结构中的元素
  • 能作为参数传递
  • 能作为返回值

高阶函数至少需要符合以下特点中的一个:

  • 接收一个或多个函数作为参数
  • 将函数作为返回值

函数作为参数

当使用一个函数作为参数时,实际上是将指定的代码传递进了目标函数

filter() 可以从序列中过滤出符合条件的元素,保存到一个新的序列中,参数:

  1. 函数,根据该函数来过滤序列(可迭代的结构)
  2. 需要过滤的序列(可迭代的结构)

返回值:过滤后的新序列(可迭代的结构)

匿名函数 lambda 函数表达式:lambda用来创建一些简单的函数,语法:lambda 参数列表 : 返回值,匿名函数一般作为参数使用

map() 对可迭代对象中的所有元素做指定操作,然后将其添加到一个新的对象中返回

sort() 默认直接比较元素大小,也可以接收一个关键字参数key,key需要一个函数作为参数,当设置了函数为参数时。每次会以列表中的一个元素作为参数来调用,使用返回值比较元素的大小

sorted() 与sort()用法一致,但是可以对任意序列进行排序,且不会影响原来的对象,而是返回一个新对象

函数作为返回值–闭包

通过闭包可以创建一些只有当前函数能访问的变量,可以将一些私有的数据藏到的闭包中

在函数内部定义一个新的函数,将内部函数作为返回值返回

形成闭包的条件:

  • 函数嵌套
  • 将内部函数作为返回值返回
  • 内部函数必须要使用到外部函数的变量
def make_averager():
    nums = []

    def averager(n):
        nums.append(n)
        return sum(nums)/len(nums)

    return averager

averager = make_averager()
print(averager(10))
print(averager(20))
print(averager(30))
print(averager(40))

闭包可以保存当前的运行环境

对闭包的一些理解https://zhuanlan.zhihu.com/p/22229197

装饰器

希望在不修改原函数的情况下,对函数进行扩展,创建一个函数,使其可以自动生产函数;通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展,在定义函数时,可以通过@装饰器,来使用指定的装饰器,来装饰当前的函数;可以同时为一个函数指定多个装饰器,这样函数将会安装从内向外的顺序被装饰

感觉就是把开头结尾的功能再封装一层函数变为装饰器,可以通用