Python基础自学(第五章-函数进阶、迭代器和生成器、装饰器、上下文管理器、变量的作用域)

第一部分:函数进阶

函数参数的传递机制(和参数的传递机制一样,采用公用内存的形式,这种共享内存的方式成为引用传递)

  • 例子
    在这里插入图片描述
    在这里插入图片描述
    利用这个共享内存的原理(但是要根据赋值机制),那么说明我们可以在函数中修改传入参数的值,例如下面例子
    在这里插入图片描述
    函数默认参数的传递机制
    有默认参数的话,Python会预先分配一个空间,当再次需要的时候可以直接到这个默认空间里面调用,这样就不用每次都生成一个额外的默认参数,但是也会出现一些特殊情况

  • 例子如下
    在这里插入图片描述
    高阶函数(即以函数作为参数或者返回一个函数的函数成为高阶函数)
    利用函数的性质我们可以做到:

  • 将函数作为参数传递给另一个函数

  • 将函数作为字典的值

  • 将函数作为另一个函数的返回值

例子如下(将函数作为字典的值):
在这里插入图片描述
再来一个例子说明一下(字典要关注键,一般用键来操作的)
在这里插入图片描述
例子如下(将函数作为参数)
在这里插入图片描述
例子如下(函数作为另一个函数的返回值)
在这里插入图片描述
另外说一下固定部分参数的函数
在Python的functools模板中提供一个叫partial()的函数,它接受一个函数作为参数并这个函数的一部分参数固定,然后返回这个新的函数
例子如下(指定函数的哪个参数)
在这里插入图片描述
例子如下(不指定函数的哪个参数,按函数参数的顺序固定)
在这里插入图片描述
介绍三个长得差不多的高阶函数

  • map(f,sq)
  • filter(f,sq)
  • reduce(f,sq)

第一个我们已经使用过了,就是接受一个函数作为参数让它作用于sq序列的每一个元素上;我们现在

介绍一下第二个
接受一个函数作为参数,通过这个函数来筛选序列中的元素,例如下面例子
在这里插入图片描述
介绍一下第三个
接受一个支持二元操作的函数(即有两个参数),实现对序列中的元素的累加计算,例如
在这里插入图片描述
这个函数还可以设定初始值,此时第一步计算的就是初始值+序列的第一个值,而不是序列第一个值和第二值相加,例如
在这里插入图片描述
用Lambda表达式代替简单的函数(省去定义简单函数的时间)

格式(其中第一个是函数的参数,第二个是函数的返回值)
在这里插入图片描述
例如这样写
在这里插入图片描述
使用global关键字在函数内部改变外部变量
例如(发现没有改变外部变量x的值)
在这里插入图片描述
此时要改变就要使用global关键字,例如
在这里插入图片描述
递归函数
指的是一个函数在执行过程中调用了本身,这通常用于分治法,即将大问题分解为若干个小的子问题

例如我们使用的阶乘函数
在这里插入图片描述
递归函数的效率问题,由于递归中存在重复计算,故而效率会低很多,这时就要采取默认参数的可变性质,利用缓存提高递归效率,例如我们所知的斐波那契数列(1,1,2,3,5,8,13…)(即后一个数是前面两个数的和)这里是这个数列的百科,看前面就行了,后面是天文没必要知道
在这里插入图片描述
然后我们用非递归的方式实现这个功能
在这里插入图片描述
在这里插入图片描述
用魔术命令验证一下两个方法的效率
在这里插入图片描述
由此发现非递归式的效率比递归式的高很多。

这时我们采取缓存机制来改善这个
在这里插入图片描述

第二部分:迭代器

每个容器类型都有一个迭代器,作用是让他们支持执行for循环操作,所以我们在用for循环对容器类时,它的内部执行过程是这样的

  • 首先获得容器的迭代器
    在这里插入图片描述
  • 调用迭代器的.next()方法,返回第一个元素,知道元素全部输出
    在这里插入图片描述
    自定义迭代器
    前面我们已经知道一个迭代器有三个方法。
  • _iter_()方法
  • .next()方法
    实现上面两个方法之后就是一个自定义的迭代器了。那么我们举个栗子,实现一个将列表反序输出的迭代器
    在这里插入图片描述
    这里用到了一个print的输出小技巧,就是加了个逗号,取消了print每次输出后面都默认输出回车的情况

除了容器对象,我们构造迭代器时还可以是一些迭代的表达式,例如Collatz猜想百度给出这个叫做冰雹猜想,有兴趣去了解一下

  • 如果n是奇数,那么就令n=3n+1
  • 如果n是偶数,那么就令n=n/2
    在这里插入图片描述
    对于上面的结果之所以能生成一个列表一样的结果但是又没有构造一个容器类,那是因为调用了迭代器的next()这个方法,有一个值就返回一个,然后继续传值计算下一个直到等于1

第三部分:生成器

生成器就是为了解决自定义类型迭代器的麻烦。刚才的Collatz猜想可以用生成器这样表达
在这里插入图片描述
生成器也是一种特殊的迭代器
在这里插入图片描述
可以看出,生成器比迭代器简单,生成器和迭代器都一样不需要一次性保存序列的所有值,而只要在需要时计算序列的下一个值,这样可以减少内存空间的使用

第四部分:装饰器

能给函数添加新特性的函数称为装饰器
例子如下,就是我们调用一个函数时希望能知道哪个函数给调用了,但是又不能给每一个函数添加一个输出语句,这时就可以采用装饰器动态地给函数添加新特性
在这里插入图片描述
更方便的写法
在这里插入图片描述
装饰器原理

  • @操作符必须是一行一个
  • 同一个装饰器可以用在多个函数上
  • 多个装饰器也能用在同一个函数上

一个装饰器用在多个函数上:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一个函数用多个装饰器:
在这里插入图片描述
装饰器工厂
利用装饰器返回装饰器就叫做装饰器工厂
在这里插入图片描述

第五部分:上下文管理器

上下文管理器可以让异常处理这个操作更加简洁
使用try处理
在这里插入图片描述
使用上下文管理器的with语句处理
在这里插入图片描述
可以看出同样的效果,但是with语句更加简洁

关于with语句的介绍

  • 格式
    在这里插入图片描述
  • 上下文管理器(实现了一个.__enter__方法和一个.__exit__方法,所以我们可以自定义上下文管理器)
    在这里插入图片描述
  • 关于其中.__enter__方法的返回值
    在这里插入图片描述
    在这里插入图片描述
  • 细说.__exit__方法的额外三个参数与异常处理的关系
    没有异常时
    在这里插入图片描述
    出现异常时
    在这里插入图片描述
    如果不想让异常信息抛出,那么可以这样设置
    在这里插入图片描述
    使用模块contextlib来方便使用上下文管理器
  • 使用模块提供的contextmanager装饰器来实现一个简单的上下文管理器
    在这里插入图片描述
    在这里插入图片描述
    需要注意的是该装饰器修饰的函数必须是一个生成器,且里面的yield执行执行一次
  • 使用这种上下文管理器的异常处理办法
    在这里插入图片描述
    使用try+finally进行改进
    在这里插入图片描述
  • 确保使用上下文管理器的对象一定执行.close()方法的closing()函数

结构如下:
在这里插入图片描述
例子如确保打开的网页一定给关闭
在这里插入图片描述

第六部分:变量的作用域

在函数中,Python会按照下面顺序在各个作用域的命名空间下寻找变量

  • 函数局部作用域
  • 闭包作用域
  • 全局作用域
  • 内置作用域

对于重名的变量,优先级就是这样的:局部>闭包>全局>内置,举个栗子逐一讲解
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

写到这里基本对Python有了一个很浅的认识了,还得继续加油,第一次写博客坚持到第五章,要给自已点个赞!有问题以后回来补咯

猜你喜欢

转载自blog.csdn.net/weixin_42341232/article/details/90301890