递归,三目运算,匿名函数,迭代器
递归,三目运算,匿名函数,迭代器,生成器......
目录
1:递归
一:什么是递归
迭代器是间接或者直接调用自己本身
二:代码演示
def foo():
print('from foo')
foo()
foo()
def bar():
print("from bar")
def test():
print("from test")
bar()
test()
三:回溯和递推
回溯就是从外向里一层一层递归调用下去,回溯阶段必须要有一个明确地结束条件,每进入下一次递归时,问题的规模都应该有所减少(否则,单纯地重复调用自身是毫无意义的)
递推就是从里向外一层一层结束递归
l = [1,[2,3,[4,5,6,[7,8,9,10,[11,12,13,14,15,[16,17,18,19,29]]]]]]
def xx(l):
for i in l:
if type(i) == list:
xx(i)
else:
print(i)
四:缺点
递归效率低下,在python中没有做过优化,其它语言有过优化
2:目运算或者三元运算
x,y=3,5
res = x if x > y else y
print(res)
3:匿名函数
匿名就是没有名字的函数
def foo(): # 这是有名函数
print('from foo')
lambda x:x**2 # 这是是匿名函数
func = lambda x:x**2
func(3)
4:内置函数
内置函数 <<<<<--点击一下就行了
5:迭代器对象和可迭代对象
一:什么是迭代?
迭代是一个重复的功能,他和循环是不一样的,迭代是在上一个结果作为开始的,循环就是重复的一个结果。
while 1:
print("from while")
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
count = 0
while count < len(l):
print(l[count])
count +=1
上方两个demo一个是循环,一个是迭代。
二:为什么要有迭代器?
list,tuple,str这三个数据类型都是可以索引取值,但是set,dict,file类型,是没有索引取值一说的。但是我们又要取值,所以语言开发者就是设计了可迭代对象
三:什么是可迭代对象
内置有__iter__方法的对象,都是可迭代数据类型
'word'.__iter__ # str
(1,).__iter__ # tuple
[1].__iter__ # list
{'k1':1}.__iter__ #dict
{'xx','oo'}.__iter__ # set
open('db.txt').__iter__ # file
四:什么是迭代器对象
可迭代对象执行__iter__()得到的结果就是迭代器对象
迭代器对象:是内部含有__iter__和__next__两个方法的对象
f = opne('db.txt',encoding='utf-8',mode='rt')
f是迭代器对象
f.close()
五:迭代器对象的使用
dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__() # 得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
iter_dic.__iter__() is iter_dic #True
print(iter_dic.__next__()) #等同于next(iter_dic)
print(iter_dic.__next__()) #等同于next(iter_dic)
print(iter_dic.__next__()) #等同于next(iter_dic)
# print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志
#有了迭代器,我们就可以不依赖索引迭代取值了
iter_dic=dic.__iter__()
while True:
try:
k=next(iter_dic)
print(dic[k])
except StopIteration:
break
#这么写太麻烦了,需要我们自己捕捉异常,调用next,所以python为我们封装了fof迭代器循环
六:for循环
dic = {'k0':0, "k2":1, "k3":3}
for key in dic:
print(dic[key])
使用for循环时,dic执行了__iter__()方法,转换成了迭代器。再根据迭代器的内置方法__next__(),一个一个取,等到值取完时。就推出了循环
七:总结
优点
它提供了一种不需要索引的迭代循环
节省内存,惰性运算
缺点
数据长度无法计算,只有结束时才知道有几个值
只能往前取值,不能往后取值
6:生成器
一:什么是生成器
定义了yield关键字的函数就是生成器
def genarotor():
print('第一次打印')
yield 1
print('第二次打印')
yield 1
print('第三次打印')
yield 1
print(type(genarotor())) # <class 'generator'>
genarotor() # 调用此函数并不会运行,需要调用next方法才能取值
二:为什么要有生成器
当程序读取大量数据时,内存可能会溢出,所以python提供了一种机制,把内容一点一点加载到内存中。
三:生成器与迭代器的关系
生成器内部有__next__和__iter__方法,所以生成器即使迭代器
示列
模拟range,range返回的结果是一个可迭代对象
def _range(start, end, se=1):
start = start
while start < end:
yield start
start += 1
print(_range(1, 100))
for i in _range(1,200):
print(i)
# 个人认为这个应该在爬取大量数据时,会用到,节省内存
7:编程思想之面向过程
面向过程编程:把一件事分成几个步骤来完成,第一步干啥,第二步干啥....
有点类似于富士康流水线,有插件的,有包装的,有焊锡的....。这些结束后一个成品出来了,xx手机就生产出来
缺点:
缺点是一环扣一环,如果某一部分出现问题,所有生产过程都中断了。
后期扩展功能不方便.....牵一发而动全身。
8:列表生成式,字典生产式,生成器生产式
列表生成式
ls = [i for i in range(10)]
ls1 = [i for i in range(20) if i % 2 == 0 ]
字典生成式
dic = {'a': 1, "b": 2, "c": 3, "d": 4}
res = {k+'sb':v for k,v in dic.items()}
print(res)
生成器生成式
l = [1,2,3,4,5]
res = (i for i in l)
print(type(res))