递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
🌰:
计算 阶乘 n!=1 x 2 x 3 x ... x n
用函数 fact (n)表达
fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact (n-1) x n
👍优点:
定义简单, 逻辑清晰。 理论上所有的递归函数都可以写成循环的方式,但循环逻辑不如递归清晰。
👋缺点:
过深的调用会导致栈溢出。
⚠️ 使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出
解决递归调用栈溢出的方法就是涌过 尾递归优化 , 事实上尾递归 和循环效果是一样的, 所以 吧循环看成一种特殊的尾递归函数也可以。
尾递归是指, 在函数返回的时候,调用本身, 并且, return 语句不能包含表达式。 这样编译器就可以将 尾递归做优化, 是递归本身无论调用多少次 都使用一个栈帧, 不会出翔帧溢出的情况。
针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。
Python 标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。
IO 编程
由于程序和运行时数据是在内存中驻留,由 CPU 这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要 IO 接口。
有两种 IO 模式 ✌️
👆同步 IO 与 异步 IO
👆第一种是CPU等着,也就是程序暂停执行后续代码,等100M的数据在10秒后写入磁盘,再接着往下执行,这种模式称为同步IO;
✌️另一种方法是CPU不等待,只是告诉磁盘,“您老慢慢写,不着急,我接着干别的事去了”,于是,后续代码可以立刻接着执行,这种模式称为异步IO。
使用异步IO来编写程序性能会远远高于同步IO,但是异步IO的缺点是编程模型复杂。
文件的读写
读文件模式打开文件对象 使用 python 内置 open () 函数 传入文件名和 标识符即可
打开后, 调用 read()方法可以一次性读取文件全部内容, python 会把内容读到内存, 用一个 str 对象表示:
⚠️ 由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来实现:
最后 调用 close () 关闭文件 「因为文件对象会占用操作系的资源, 并且操作系统统一时间可以打开文件的数量也是有限的」
由于一直调用太频繁 所以 python 引入了 with 语句 来自动帮助 调用 close 方法
调用 read ( ) 会一次性读取文件的全部内容,如果文件有 10G,内存就爆了,所以,要保险起见,可以反复调用 read ( size ) 方法,每次最多读取 size 个字节的内容。另外,调用 readline( ) 可以每次读取一行内容,调用 readlines ( ) 一次读取所有内容并按行返回 list。因此,要根据需要决定怎么调用。
⚠️ 如果文件很小,read ( ) 一次性读取最方便;如果不能确定文件大小,反复调用 read (size) 比较保险;如果是配置文件,调用 readlines( ) 最方便
file-like Object
像 open( ) 函数返回的这种有个 read( ) 方法的对象,在 Python 中统称为 file-like Object。除了 file外,还可以是内存的字节流,网络流,自定义流等等。file-like Objec t不要求从特定类继承,只要写个read( ) 方法就行。
StringIO 就是在内存中创建的 file-like Object,常用作临时缓冲。
网友评论