一、迭代器
1、什么是迭代器:
假设现在没学过for循环
器=》工具
迭代:是一个重复的过程,但每次重复都是基于上一次的结果而来的
迭代器:就是一种不依赖于索引的取值工具
2.为什么要用迭代器:
1.迭代器是一种通用的迭代取值方法(可以无视是否有索引)
2.惰性计算,节省内存。迭代器在生成时,并没有产生值,并不会占用很多内存。在每次使用next方法后,会临时计算一个值,更节省内存。
names=["egon",'lqz','yj']
count = 1
while count < len(names):
print(names[count])
count+=1
2、为何要有迭代器
特性:
①、是一种通用的迭代取值方案
②、惰性计算,节省内存
3、如何用迭代器
在下面我们会使用到双下划线加方法名的使用,如__iter__(),__next__(),其实和iter(),next()是等同的
dic = {"name": "yang", 'age': 18, 'gender': "male"}
dic_iterator = dic.__iter__()
res1 = dic_iterator.__next__()
res2 = dic_iterator.__next__()
res3 = dic_iterator.__next__()
print(res1,res2,res3)
------------------------------------
name age gender
dic_iterator.__next__() # 抛出异常
-----------------------------------
Traceback (most recent call last):
File "xxx.py", line 44, in <module>
dic_iterator.__next__()
StopIteration
'''
当迭代器中取完了值之后,会抛出异常,提示我们已经取完了值,抛出StopIteration,因为在我们直接拿到
一个迭代器的时候,我们是不知道这个迭代器到底有多少个值的
'''
while True:
try:
res = dic_iterator.__next__()
print(res)
except StopIteration:
break
'''
try:
代码
except 条件:
代码
是一种处理异常的情况,和java的异常处理机制try,catch类似,目前我们只需要记住这个格式,他而已帮助我们捕获异常,在出现了我们指定的异常的时候,会帮助我们执行下部的代码,防止程序崩溃
'''
二:可迭代对象与迭代器对象
2.1 内置有iter方法的类型称之为:可迭代的对象/类型
所有的常用类型,都是可以被转成迭代器的对象,也叫可迭代对象
1、字典dict
2、集合set
3、文件对象(也是迭代器对象)
f = open('a.txt')
f.__iter__()
4、字符串str
5、列表list
6、元组tuple
2.2 迭代器对象: 内置有next方法、内置有iter方法
dic = {"name": "egon", 'age': 18, 'gender': "male"}
dic_iterator1 = dic.__iter__()
dic_iterator1.__next__()
print(dic_iterator1.__iter__().__iter__().__iter__() is dic_iterator1)
dic_iterator2 = dic.__iter__()
可迭代对象可以用iter()方法转化成迭代器对象,迭代器对象也可以再使用iter方法,但是得到的是它本身,这个特性是为了迎合for循环的工作原理,下面会讲到。
对于文件对象,它即是可迭代对象,又是迭代器对象,做成这样的原因是因为某些文件可以很大,因为迭代器的特性,每次调用才产生值,不会造成内存冲击,而其他的类型,一般不会存放非常大量的数据
三:for循环的工作原理
dic = {"name": "egon", 'age': 18, 'gender': "male"}
dic_iterator = dic.__iter__()
while True:
try:
res = dic_iterator.__next__()
print(res)
except StopIteration:
break
for k in dic:
print(k)
'''
步骤1 dic_iterator = dic.__iter__()
步骤2 k=dic_iterator.__next__(),执行循环体代码
步骤3 循环往复,直到抛出异常,for循环会帮我们捕捉异常结束循环
'''
dic = {"name": "egon", 'age': 18, 'gender': "male"}
dic_iterator = dic.__iter__()
for k in dic_iterator:
print(k)
print(dic_iterator)
四:基于同一迭代器的重复取值,效果如何?
示例1:
dic = {"name": "egon", 'age': 18, 'gender': "male"}
dic_iterator = dic.__iter__()
while True:
try:
res = dic_iterator.__next__()
print(res)
except StopIteration:
break
print('='*20)
dic_iterator = dic.__iter__()
while True:
try:
res = dic_iterator.__next__()
print(res)
except StopIteration:
break
示例2:
dic = {"name": "egon", 'age': 18, 'gender': "male"}
for k in dic: # dic.__iter__()
print(k)
for k in dic: # dic.__iter__()
print(k)
二、生成器:自定义迭代器
但凡是函数内出现了yield关键字,调用函数不会执行函数整体代码,而是得到一个返回值,这个返回值就是生成器。
def func():
print("hello1")
yield 111
print("hello2")
yield 222
print("hello3")
yield 333
g = func()
print(g) # 生成器本质就是迭代器
res=next(g)
print(res)
res=next(g)
print(res)
res=next(g)
print(res)
next(g)
2、yield VS return
(1)相同点:都可以用来返回值
(2)不同点:
return只能返回一次值,函数就立即结束了
yield能返回多次值,yield可以挂起函数(即停住函数)
案例
def func():
res=0
while True:
res+=1
yield res
g=func()
for i in g:
print(i)
总结迭代器的优缺点
优点:
1、是一种通用的迭代取值方案
2、惰性计算,节省内存
缺点:
1、取值不如索引、key的取值方式灵活
2、取值是一次性的,只能往后取,不能预估值的个数
小练习:用迭代器写一个range功能
def my_range(start, stop, step=1):
while start < stop:
yield start
start += step
for i in my_range(1,5,2):
print(i)
三、面向过程编程
面向过程:
核心是“过程”二字,过程指的就是做事的步骤
也就是先干什、再干什么、后干什么。。。
基于该思想写程序就好比设计一条条的流水线
优点:可以把复杂的问题流程化,进而简单化
缺点:牵一发而动全身,扩展性差
应用场景:面向过程的程序设计一般用于那些功能一旦实现之后就很少需要改变的场景, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程去实现是极好的,但如果你要处理的任务是复杂的,且需要不断迭代和维护, 那还是用面向对象最为方便。
四、生成式
1、列表生成式
l=[i**2 for i in range(5)]
print(l)
-----------------------------
[0, 1, 2, 3, 4]
'''
1.for的左边,只要是一个有返回值的就行,可以是变量,可以是函数len(i),也可以是常数
2.在for条件后,还可以跟if条件
'''
names=['lqz_sb','yj_sb','jason_sb','egon']
l=[name for name in names if name.endswith('sb')]
print(l)
---------------------------------------
['lqz_sb', 'yj_sb', 'jason_sb']
2、集合生成式
res={i for i in range(5)}
print(res,type(res))
--------------------------------
{0, 1, 2, 3, 4} <class 'set'>
3、字典生成式
res={f'k{i}': i**2 for i in range(5)}
print(res)
-------------------------------------------
{'k0': 0, 'k1': 1, 'k2': 2, 'k3': 3, 'k4': 4} <class 'dict'>
4、生成器表达式
对于简单的一些生成器,可直接这样生成
res=(i for i in range(5))
print(res,type(res))
----------------------------------
<generator object <genexpr> at 0x000001E0C777C970> <class 'generator'>
print(next(res))
print(next(res))
print(next(res))
print(next(res))
print(next(res))
print(next(res))
------------------------
0
1
2
3
4
简单的应用用途:
计算1-1000000的和
nums=(i for i in range(1000000))
res=sum(nums)
print(res)
----------------------
499999500000
计算一个文档中的字符个数
with open('01 迭代器.py', mode='rt', encoding='utf-8') as f:
data=f.read()
print(len(data)) # 2202
res=0
for line in f:
res+=len(line)
res = sum((len(line) for line in f))
res = sum(len(line) for line in f)
print(res)
五、内置函数
'''abs()取绝对值'''
print(abs(-1))
'''
all() 函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,
如果是返回 True,否则返回 False。
元素除了是 0、空、None、False 外都算 True。
'''
print(all([True,11,0]))
print(all([]))
---------------------------
False
True
'''
all() 函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,
如果是返回 True,否则返回 False。
元素除了是 0、空、None、False 外都算 True。
'''
print(any([True,False,0]))
print(any([]))
--------------------------------
True
False
'''
callable() 函数用于检查一个对象是否是可调用的。如果返回 True,object 仍然
可能调用失败;但如果返回 False,调用对象 object 绝对不会成功。
对于函数、方法、lambda 函式、 类以及实现了 __call__ 方法的类实例, 它都返回 True。
'''
print(callable(len))
--------------
True
'''
ord()函数主要用来返回对应字符的ascii码,chr()主要用来表示ascii码对应的字符
他的输入时数字,可以用十进制,也可以用十六进制。
'''
print(chr(90))
print(ord('Z'))
--------------------------
Z
90
'''
dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数
时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。
如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
'''
l=[1,2,3]
print(dir(l))
---------------------
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__'等等
'''
python divmod() 函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)。
'''
print(divmod(10,3))
-----------------------
(3, 1)