python基础2.0
递归函数:函数内部调用自身本身
def fact(n): if n==1: return 1 return n * fact(n - 1)
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
尾递归优化:
def fact(n): return fact_iter(n, 1) def fact_iter(num, product): if num == 1: return product return fact_iter(num - 1, num * product)
可以看到,return fact_iter(num - 1, num * product)
仅返回递归函数本身,num - 1
和num * product
在函数调用前就会被计算,不影响函数调用。
fact(5)
对应的fact_iter(5, 1)
的调用如下:
===> fact_iter(5, 1) ===> fact_iter(4, 5) ===> fact_iter(3, 20) ===> fact_iter(2, 60) ===> fact_iter(1, 120) ===> 120
python的高级特性
1)切片
L[0:9:2]前10个数,每两个取一个
2)迭代
for ... in
因为dict的存储不是按照list的方式顺序排列,所以,迭代出的结果顺序很可能不一样。
字典的迭代
默认情况下,dict迭代的是key。如果要迭代value,可以用for value in d.values()
,如果要同时迭代key和value,可以用for k, v in d.items()
。
由于字符串也是可迭代对象,因此,也可以作用于for
循环:
>>> for ch in 'ABC': ... print(ch) ... A B C
所以,当我们使用for
循环时,只要作用于一个可迭代对象,for
循环就可以正常运行,而我们不太关心该对象究竟是list还是其他数据类型。
3)列表生成式
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' } >>> [k + '=' + v for k, v in d.items()] ['y=B', 'x=A', 'z=C']
运用列表生成式,可以快速生成list,可以通过一个list推导出另一个list,而代码却十分简洁
生成器:
generator是非常强大的工具,在Python中,可以简单地把列表生成式改成generator,也可以通过函数实现复杂逻辑的generator。
要理解generator的工作原理,它是在for
循环的过程中不断计算出下一个元素,并在适当的条件结束for
循环。对于函数改成的generator来说,遇到return
语句或者执行到函数体最后一行语句,就是结束generator的指令,for
循环随之结束。
请注意区分普通函数和generator函数,普通函数调用直接返回结果:
>>> r = abs(6) >>> r 6
generator函数的“调用”实际返回一个generator对象:
>>> g = fib(6)
>>> g
<generator object fib at 0x1022ef948>
定义生成器:generator function
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
生成式和生成器的区别
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x1022ef630>
迭代器:
直接作用于for
循环的对象统称为可迭代对象:Iterable
。
生成器不但可以作用于for
循环,还可以被next()
函数不断调用并返回下一个值,直到最后抛出StopIteration
错误表示无法继续返回下一个值了。 可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
凡是可作用于for
循环的对象都是Iterable
类型;
凡是可作用于next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。
高阶函数:
map()
函数接收两个参数,一个是函数,一个是Iterable
,map
将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator
返回。
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])) ['1', '2', '3', '4', '5', '6', '7', '8', '9']
reduce
把一个函数作用在一个序列[x1, x2, x3, ...]
上,这个函数必须接收两个参数,reduce
把结果继续和序列的下一个元素做累积计算
>>> from functools import reduce >>> def fn(x, y): ... return x * 10 + y ... >>> def char2num(s): ... digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9} ... return digits[s] ... >>> reduce(fn, map(char2num, '13579')
用lambda函数进一步简化成:
from functools import reduce DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9} def char2num(s): return DIGITS[s] def str2int(s): return reduce(lambda x, y: x * 10 + y, map(char2num, s))
filter函数:
和map()
类似,filter()
也接收一个函数和一个序列。和map()
不同的是,filter()
把传入的函数依次作用于每个元素,然后根据返回值是True
还是False
决定保留还是丢弃该元素
一个序列中的空字符串删掉,可以这么写:
def not_empty(s): return s and s.strip() list(filter(not_empty, ['A', '', 'B', None, 'C', ' '])) # 结果: ['A', 'B', 'C']
filter()
这个高阶函数,关键在于正确实现一个“筛选”函数。 注意到filter()
函数返回的是一个Iterator
,也就是一个惰性序列,所以要强迫filter()
完成计算结果,需要用list()
函数获得所有结果并返回lis
def is_odd(n): return n % 2 == 1 tmplist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) newlist = list(tmplist) print(newlist)
sorted()
也是一个高阶函数。用sorted()
排序的关键在于实现一个映射函数。
sorted函数:sorted(iterable,key,reverse)
其中iterable表示可以迭代的对象, key是一个函数,用来选取参与比较的元素,reverse则是用来指定排序是倒序还是顺序,reverse=true则是倒序,reverse=false时则是顺序,默认时reverse=false
以下返回值都是单一的key值排列或者value值排列
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85} >>>sorted(d.keys()) ['Bob', 'Michael', 'Tracy'] >>>sorted(d.values()) [75, 85, 95] >>>sorted(d) ['Bob', 'Michael', 'Tracy']#默认就是根据key值排序 >>>sorted(d,key=lambda x: d[x])#根据value值的大小对key排序 ['Bob', 'Tracy', 'Michael']
以下返回值是既包含key又包含value的列表,与上面的区别就是sorted的第一个参数不是d而是d.items(),d.items会把d变成一个可迭代对象.
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85} >>>d.items() dict_items([('Michael', 95), ('Bob', 75), ('Tracy', 85)]) >>>sorted(d.items(),key=lambda x : x[1]) [('Bob', 75), ('Tracy', 85), ('Michael', 95)] >>>d = {'data1':3,'da':1,'dat':2,'data22':4,'aa':3,'ff':0} >>>sorted(d.items(),key=lambda x :(x[1],x[0]))#对dict先根据value排序,value相等的根据key排序 [('ff', 0), ('da', 1), ('dat', 2), ('aa', 3), ('data1', 3), ('data22', 4)] sorted(d.items())#根据key值对整个dict排序 [('aa', 3), ('da', 1), ('dat', 2), ('data1', 3), ('data22', 4), ('ff', 0)]
返回函数
高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
def lazy_sum(*args): def sum(): ax = 0 for n in args: ax = ax + n return ax return sum
我们在函数lazy_sum
中又定义了函数sum
,并且,内部函数sum
可以引用外部函数lazy_sum
的参数和局部变量,当lazy_sum
返回函数sum
时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。
闭包:
def 外层函数(参数): def 内层函数(): print("内层函数执行", 参数) return 内层函数 内层函数的引用 = 外层函数("传入参数") 内层函数的引用()
匿名函数:
lambda x: x * x
装饰器:https://blog.csdn.net/weixin_39541558/article/details/79972104
在面向对象(OOP)的设计模式中,decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。
decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。
偏函数:
functools.partial
可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
functools.partial
就是帮助我们创建一个偏函数的,不需要我们自己定义int2()
,可以直接使用下面的代码创建一个新的函数int2
:
>>> import functools >>> int2 = functools.partial(int, base=2) >>> int2('1000000') 64 >>> int2('1010101') 85
