迭代器,for循环本质,生成器,常用内置方法,面向过程编程
一、迭代器
1、迭代:更新换代(重复)的过程,每次的迭代都必须基于上一次的结果
迭代器:迭代取值的工具
2、迭代器给你提供了一种不依赖于索引取值的方式
3、可以迭代取值的对象:字符串,列表,元组,字典,集合等
4、可迭代对象:内置有__iter__方法的都叫做可迭代对象
5、针对双下划线开头和结尾的方法:读法是双下+方法名
6、基本数据类型中,是可迭代对象的有:str、list、tuple、dict、set
文件对象(执行内置的__iter__之后还是本身,没有任何变化):文件对象本身就是迭代器对象
7、迭代器对象
①、可迭代对象执行内置的__iter__方法得到的就是该对象的迭代器对象
②、迭代器对象内置有__iter__方法和__next__方法
③、迭代器对象一定是可迭代对象
④、迭代器对象只能通过执行__next__方法取到迭代器内的值,执行一次返回一个,执行次数超过迭代器内值的个数时报错(StopIteration)
⑤、迭代器取值的特点:只能往后依次取,不能后退
⑥、迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本身(******)
8、异常处理
while True:
try:
print(iter_d.__next__())
except StopIteration:
print("老母猪生不动了")
break
该程序会一直执行try后面的代码,当遇到except后面的错误时,执行except后面的程序,一般是终止循环,如果遇到的不是except后面的错误,则正常报错。
9、文件对象本身就是迭代器对象,为什么还内置有__iter__方法?
这就要谈到for循环的本质了。
二、for循环的本质
1、for循环只能用于可迭代对象
2、for循环内部的本质:
①、将in后面的对象调用__iter__转换成迭代器对象
②、调用__next__迭代取值
③、内部有异常捕获StopIteration,当__next__报这个错,自动结束循环
3、可迭代对象:内置有__iter__方法的
迭代器对象:即内置有__iter__也内置有__next__方法
4、迭代取值的优缺点:
优点:
①、不依赖于索引取值
②、内存中永远只会占一份空间,不会导致内存溢出
缺点:
①、不能够获取指定的元素
②、取完之后会报StopIteration错误
5、for循环只能循环可迭代对象,而迭代器对象也是可迭代对象,当for循环一个迭代器对象时,会先对其调用__iter__方法,如果迭代器对象没有内置__iter__方法,就会报错。
三、生成器
1、用户自定义的迭代器,本质就是迭代器
2、形式
def func():
print("first")
yield 666
print("second")
yield 777
print("third")
yield 888
3、函数定义体内部有yield关键字,函数名加括号次并不会执行函数体代码,而是会将其变成一个生成器,也叫作生成器初始化,生成器与迭代器一样通过__next__取值,而取到的值就是yield后面传的值,可以传一个值,也可以传多个值,传多个值会以元组的形式存储。生成器执行__next__方法时,遇到yield就会暂停,并将yield后面的值传出来。并且生成器执行__next__方法次数超过yield传值的个数时,也会报StopIteration错误。
4、例子,自己写一个range函数,简单模仿内置range函数
def my_range(start, end, step):
while start < end:
yield start
start += step for j in my_range(1, 100, 2):
print(j)
5、yield表达式形式(了解)
def dog(name):
print("%s准备开吃"%name)
while True:
food = yield
print("%s吃了%s"%(name,food)) g = dog("egon")
# 初始化生成器,并将“egon”传进去
g.__next__()
# 必须先将代码运行至yield才能为其传值
g.send("狗不理包子")
# 给yield左边的变量传参,触发了__next__方法
g.send("饺子") # 输出
# egon准备开吃
# egon吃了狗不理包子
# egon吃了饺子
注意点:要有一个变量接收yield传的值,传值之前,必须要将代码运行到yield处,传值必须要调用send()方法
6、yield与return
①、yield帮你提供了一种自定义生成器方式
②、会帮你将函数的运行状态暂停住
③、可以返回值
与return之间的异同点
①、相同点:都可以返回值,并且都可以返回多个
②、不同点:yield可以返回多次值,而return只能返回一次值(函数体代码运行到return立即结束)
yield还可以接受外部传入的值
四、生成器表达式
1、之前学了三种生成式:列表生成式、字典生成式、集合生成式,唯独没有元组生成式,那是因为用小括号括起来的式子就不再是一个元组了,而变成了一个生成器。
list1 = [1, 2, 3, 4, 5]
d = (i for i in list1 if i != 2)
print(d)
# 输出
# <generator object <genexpr> at 0x031B28A0>
# 此时的d已经是一个生成器了
2、上述这种形式的式子就是生成器表达式
3、生成器的特点是省内存,无论在什么时候,内存中只有一块内存空间被占用。
4、生成器也可以调用__iter__和__next__方法,说明生成器本质上就是一个迭代器。
5、生成器不会主动执行任何一行代码
# 一道面试题
def add(n, i):
return n+i
def test():
for i in range(4):
yield i
g = test()
for n in [1, 10]:
g = (add(n, i) for i in g) res = list(g) # 问最终的res是什么?
A. res = [10, 11, 12, 13]
B. res = [11, 12, 13, 14]
C. res = [20, 21, 22, 23]
D. res = [21, 22, 23, 24] # 分析:首先定义了两个函数,代码运行到g = test()时,由于test函数内部有yield关键字,所以test函数体代码并不会运行,并且g已经初始化为一个生成器,执行到for循环语句,第一次循环,n虽然是等于1传入,但循环内部的代码只是一个赋值语句,实际代码并未执行,此时g = (add(n, i) for i in test()),同理,进行第二次循环的时候,n = 10,g = (add(n, i) for i in (add(n, i) for i in test())),循环结束得到上述两个结果。真正执行代码是运行到list(g)的时候,list()内部是基于for循环将g这个生成器内的值一一取出来,先执行for i in test(),取出[0, 1, 2, 3]四个值,分别交给add函数,由于此时n = 10,所以for i in (add(n, i) for i in test())取出的值为[10, 11, 12, 13],再交给add函数,与n相加,得到[20, 21, 22, 23] # 分析:n为什么等于10?
两次for循环,都没有执行代码,所以n的值不会传入表达式,执行完for循环后,n = 10,真正执行代码时,来找n的值,此时n等于10
五、常用内置方法
https://www.cnblogs.com/Dominic-Ji/articles/11151528.html#_label2
# print(abs(-11.11)) # 求绝对值
# l = [0,1,0]
# print(all(l)) # 只要有一个为False就返回False
# print(any(l)) # 只要有一个位True就返回True
def index(): username = '我是局部名称空间里面的username'
# print(locals()) # 当前语句在哪个位置 就会返回哪个位置所存储的所有的名字
print(globals()) # 无论在哪 查看的都是全局名称空间
# index()
# print(bin(10))
# print(oct(10))
# print(hex(10))
# print(int('0b1010',2)) # print(bool(1))
# print(bool(0)) # s = 'hello'
# print(s.encode('utf-8'))
# print(bytes(s,encoding='utf-8')) # 可调用的(可以加括号执行相应功能的)
# l = [1,2,3]
# def index():
# pass
# print(callable(l))
# print(callable(index)) # print(chr(97)) # 将数字转换成ascii码表对应的字符
# print(ord('a')) # 将字符按照ascii表转成对应的数字 """
面向对象需要学习的方法
classmethod
delattr
getattr
hasattr
issubclass
property
repr
setattr
super
staticmethod
"""
# dir获取当前对象名称空间里面的名字
# l = [1,2,3]
# print(dir(l))
#
# import test
# print(dir(test))
# print(test.name) # divmod 分页器 # print(divmod(101,10))
# total_num,more = divmod(900,11)
# if more:
# total_num += 1
# print('总页数:',total_num) # enumerate 枚举
# l = ['a','b']
# for i,j in enumerate(l,1):
# print(i,j) # eval exec
s = """
print('hello baby~')
x = 1
y = 2
print(x + y) """
# eval(s)
# exec(s) # eval不支持逻辑代码,只支持一些简单的python代码
s1 = """
print(1 + 2)
for i in range(10):
print(i)
"""
# eval(s1)
# exec(s1) # name = 'jason'
# s2 = """
# name
# """
# print(eval(s2)) # format 三种玩法
# {}占位
# {index} 索引
# {name} 指名道姓 # print(globals())
def login():
"""
一起嗨皮
:return:
"""
# print(help(login)) # isinstance 后面统一改方法判断对象是否属于某个数据类型
# n = 1
# print(type(n))
# print(isinstance(n,list)) # 判断对象是否属于某个数据类型 # print(pow(2,3)) # print(round(3.4))
六、面向过程编程
1、就类似于设计一条流水线
2、好处:将复杂的问题流程化,从而简单化
坏处:可扩展性较差,一旦需要修改,整体都会受到影响
# 注册功能
# 1.获取用户输入
def get_info():
while True:
username = input(">>>:").strip()
if not username.isalpha(): # 判断字符串不能包含数字
print('不能包含数字')
continue
password = input('>>>:').strip()
confirm_password = input("confirm>>>:").strip()
if password == confirm_password:
d = {
'1':'user',
'2':'admin'
}
while True:
print("""
1 普通用户
2 管理员
""")
choice = input('please choice user type to register>>>:').strip()
if choice not in d:continue
user_type = d.get(choice)
operate_data(username,password,user_type)
break
else:
print('两次密码不一致') # 2.处理用户信息
def operate_data(username,password,user_type):
# jason|123
res = '%s|%s|%s\n'%(username,password,user_type)
save_data(res,'userinfo.txt') # 3.存储到文件中
def save_data(res,file_name):
with open(file_name,'a',encoding='utf-8') as f:
f.write(res) def register():
get_info() register()
七、补充
1、读取一个文件并返回每行数据的长度
with open('test1.txt', 'w', encoding='utf-8') as f:
for line in range(1000):
f.write(f'www{line}aaa' * (line + 1) + '\n') # 列表推导式: 处理数据量大的文件会导致内存溢出.
res = [len(line) for line in open('test1.txt', 'r', encoding='utf-8')]
# print(res) # 生成器表达式: 处理数据量大的文件推荐使用.
res2 = (len(line) for line in open('test1.txt', 'r', encoding='utf-8'))
print(res2) # <generator object <genexpr> at 0x000002B3748FD0A0>
print(next(res2))
print(next(res2))
2、一个面试题
# 题目
def multipliers():
return [lambda x: i*x for i in range(4)]
print([m(2) for m in multipliers()])
# 输出[6, 6, 6, 6] # 改写
def multipliers2():
list1 = []
for i in range(4):
def func(x)
return x * i
list1.append(func)
return list1
print([m(2) for m in multipliers2()]) # 原因:闭包函数的延迟绑定
# 在内层函数执行时才会绑定变量i #如果
def multipliers():
return [lambda x,i =i: i*x for i in range(4)]
print([m(2) for m in multipliers()])
# 输出[0, 2, 4, 6] # 改写
def multipliers2():
list1 = []
for i in range(4):
def func(x,i=i)
return x * i
list1.append(func)
return list1
print([m(2) for m in multipliers2()]) # 由于在内层函数定义阶段,i是由参数传入的值,那么func函数就能直接拿到i的值。每一次for循环i的值都不一样,所以每一次func函数的定义体代码都不一样。
3、三个老母鸡的故事
g,g1,g2里面的值都是指向同一个内存地址,被一个老母鸡取走了,其他母鸡就没有了。
def demo():
for i in range(4):
yield i
g = demo()
g1 = (i for i in g)
g2 = (i for i in list(g1)) print(list(g))
print(list(g1))
print(list(g2))
# 输出
[]
[]
[0, 1, 2, 3]
迭代器,for循环本质,生成器,常用内置方法,面向过程编程的更多相关文章
- day20 匿名函数,内置函数,面向过程编程
目录 有名函数 匿名函数 max() min() sorted map filter 内置函数 面向过程编程 有名函数 def f1(): print('my name is f1') f1() my ...
- python迭代器-迭代器取值-for循环-生成器-yield-生成器表达式-常用内置方法-面向过程编程-05
迭代器 迭代器 迭代: # 更新换代(其实也是重复)的过程,每一次的迭代都必须基于上一次的结果(上一次与这一次之间必须是有关系的) 迭代器: # 迭代取值的工具 为什么用迭代器: # 迭代器提供了一种 ...
- python循环与基本数据类型内置方法
今天又是充满希望的一天呢 一.python循环 1.wuile与else连用 当while没有被关键'break'主动结束的情况下 正常结束循环体代码之后会执行else的子代码 "" ...
- python字符串常用内置方法
python字符串常用内置方法 定义: 字符串是一个有序的字符的集合,用与存储和表示基本的文本信息. python中引号中间包含的就是字符串. # s1='hello world' # s2=&quo ...
- python基础--迭代器、生成器、内置函数、面向对象编程
迭代器:迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问完结束.迭代器只能往前不会后退 迭代:更新换代(重复)的过程,每次的迭代都必须基于上一次的结果 迭代器:迭代取值的工具 使用迭代器的 ...
- Day06:迭代器,生成器,生成表达式,面向过程编程,包及常用模块
今日内容:1.迭代器(****)2.生成器(***)3.生成器表达式(*****)4.面向过程编程(*****)5.包的使用(***)6.常用模块 logging (*****) re ( ...
- Day06for循环和字符串的内置方法
Day06 1.for循环(迭代器循环) while循环 条件循环,循环是否结束取决于条件的真假 for循环,迭代器循环,多用于循环取值,循环是否结束取决于被循环数据的元素个数 2.range(1,5 ...
- while.for循环和基本数据类型内置方法
while循环补充说明 流程控制之for循环 基本数据类型内置方法 内容详细 1.死循环 真正的死循环是一旦执行,Cpu的功耗会急速上升 知道系统采取紧急措施 所以 尽量不要让cpu长时间不断运算. ...
- Python 类的常用内置方法
类的内置方法(魔法方法): 凡是在类内部定义,以__开头__结尾的方法,都是类的内置方法,类的内置方法,会在满足某种条件下自动触发. 1.1__new__ __new__:在___init__触发前, ...
随机推荐
- Dimension reduction
materials: 1. Dimension Reduction - IsoMap
- 使用 Laravel-Excel 和流的方法导出 Excel
1.使用 laravel-excel 扩展包导出 扩展包的 3.0 的版本和 2.0 相比做了很多的改动,个人感觉更容易使用了.扩展包给出了很多基于 query 的导出,视图的导出.下面例子为基于 a ...
- 显示目录文件命令 - ls
1) 命令名称:ls 2) 英文原意:list 3) 命令所在路径:/bin/ls 4) 执行权限:所有用户 5) 功能描述:显示目录文件 6) 语法: ls 选项[-ald][文件或目录] -a 显 ...
- c#自带压缩类实现的多文件压缩和解压
用c#自带的System.IO.Compression命名空间下的压缩类实现的多文件压缩和解压功能,缺点是多文件压缩包的解压只能调用自身的解压方法,和现有的压缩软件不兼容.下面的代码没有把多文件的目录 ...
- json_encode中文不转义问题
//php5.3之后才有这个参数,这样存入数据库中的中文json数据就不会转义,也能被正确解析1JSON_UNESCAPED_UNICODE(中文不转为unicode ,对应的数字 256) JSON ...
- laravel路由组中namespace的的用法详解
做公司一个项目的时候发现laravel框架中可以省去action的路径前缀的用法: ps:用简短的话来理解就是说在路由组中定义namespace,可以省去你路由的前缀下面看例子 最终显示如下: 定义的 ...
- HTMLinput标签
<input> 标签用于搜集用户信息. 常用的属性: type指定输入项的类型 name定义 input 元素的名称. id给输入项取一个名字,方便后期找到和操作 type指定输入项的类型 ...
- 掩膜(mask)
1.掩膜(mask)的定义 用选定的图像,图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程.用于覆盖的特定图像或物体称为掩模或模板.光学图像处理中,掩模可以足胶片,滤光片 ...
- Solr与对应Jdk版本的关系
Solr各版本下载地址:http://archive.apache.org/dist/lucene/solr/ 下载的包里面的CHANGES.txt 有当前版本需要的说明.
- 洛谷 1219:八皇后 (位运算 & DFS)
题目链接: https://www.luogu.org/problem/show?pid=1219#sub row:受上面的皇后通过列控制的位置 ld:受上面的皇后通过从右至左的斜对角线控制的位置 r ...