Python day15:迭代器+生成器+面向过程编程+生成式

一、迭代器
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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352