python_可迭代对象,迭代器,生成器

一。可迭代对象

概念:可以用for操作的对象都是可迭代对象

举例:list tuple str set dict  都是可迭代对象

如何判断是否是可迭代对象:

  方法一:isinstance(obj,Iterable) ,需要先导入Iterable(from typing import Iterable)

      

  方法二:有__iter__属性就是可迭代对象

    print(hasattr(list, "__iter__"))

  print(hasattr(tuple, "__iter__"))
  print(hasattr(str, "__iter__"))
  print(hasattr(set, "__iter__"))
  print(hasattr(dict, "__iter__"))


#不可迭代对象

for i in int(1): #会报错:TypeError: 'int' object is not iterable
print(i)

 

可迭代对象range()的实现方法:

  


def my_range(stop):
"""模拟了python2中的range"""
value = 1
result = []
while value < stop:
result.append(value)
value += 1
return result


# python2 中有xrange这个函数
# python3 中把python2 rangexrange 整合为 "range"

if __name__ == '__main__':
# print(my_range(10))

print(isinstance(my_range(10), Iterable))

# 如果输入的数字过大就会很慢
# print(my_range(999999999999999999))

 

二。迭代器

#如何判断某个对象是不是迭代器
#方法一:isinstance(obj,Iterator) ,需要先导入Iterator
#方法二:看对象有没有__iter__属性和__next__属性
#迭代器协议:
#1。迭代器类型必须实现 __iter__ __next__ __next__python2中是next,没有下滑线)
#2__iter__ 方法必须返回self
#3__next__必须返回下一个值,如果没有下一个抛出StopIteration异常
from typing import Iterator

obj = range(1,2)
obj1= iter(range(1,2))

#方法一:
print(isinstance(obj,Iterator)) #False

print(isinstance(obj1,Iterator)) #True

print(isinstance([1,2,3],Iterator)) #False

#方法二:
for attr in dir(list):
print(attr) #只有:__iter__属性

for attr in dir(obj1):
print(attr) #有:"__iter__" "__next__" 属性

 

 

三。生成器

#生成器的意义:为了快速创建一个迭代器
# yield的关键字,来实现快速创建迭代器,生成器一定是一个迭代器
#yield用法:在函数中使用
#如果一个函数中有yield关键字,调用函数的时候不会执行函数的内容,会返回一个对象(这个对象类型是生成器类)

 

四:自己实现一个生成器

# 手动实现1-3的平方,返回1 4 9
result = []
for i in [1, 2, 3]:
result.append(i * i)
print(result)


# 第一种:迭代器实现
class Squares(object):
def __init__(self, start, stop):
self.start = start
self.stop = stop

def __iter__(self):
return self

def __next__(self):
if self.start > self.stop:
raise StopIteration
current = self.start * self.start
self.start += 1
return current


# 第第二种:生成器实现
def squares(start, stop):
for i in range(start, stop+1):
yield i * i

#第三种:
squares2 = (i*i for i in range(1,4))

#第二种方法和第三种方法对比:都是一样的类型 ,返回的都是:<class 'generator'>
print(type(squares(1,4)))
print(type(squares2))
if __name__ == '__main__':
#迭代器实现
# iterator = Squares(1, 3)
# for i in result:
# print(i)

#生成器实现
iterator = squares(1, 3)
for i in result:
print(i)

 

五:生成器的执行过程

def f():
print("开始执行")
yield 1
print("~~~~~~~~~~")
yield 2


def f2():
result = []
result.append(1)
result.append(2)
return result


#当要访问生成器的__next__方法时,函数会变成 running 状态,当执行完成yield时,函数变成非running状态(即挂起)
# 只有再次执行生成器的__next__方法时函数才会唤醒
#疑问:什么情况下会执行生成器对象的__next__方法那?
# (获取生成器下一个值的时候【参考f()f2(),这两个方法最终结果是一样的,在执行f()时第二次 yield 2 就是获取下一个值,也就是执行__next__】)
if __name__ == '__main__':
obj = f()
#如果有yield返回的是 generator 对象,如果没有yield 返回的是"开始执行"
print(obj)
print(type(obj))
print(obj.__next__())
print(obj.__next__())

#yield return区别
#共同点:都是python的关键字
#不同点:return 是结束函数并返回值,yield是暂时离开函数
#方法一:isinstance(obj,Iterable) ,需要先导入Iterable
posted @ 2021-03-26 19:54  1142783691  阅读(114)  评论(0编辑  收藏  举报