Python之 反射、迭代器、生成器
一、反射
反射就是通过 内置函数getattr() 以字符串的形式导入模块,以字符串的形式调用模块/对象里方法
l=['add','del','set','find']
for i in l:
print(i)
choice=input("请输入您需要的操作:".strip())
mode=__import__(choice) #相当于 import 模块
getattr(mode,choice[0])() #获取 模块里定义的方法(函数)并且执行;
二、迭代器
Python的数据类型分为
不可迭代类型(数字、布尔值)
可迭代类型(字符串、列表、元组、集合、字典、文件句柄、range、枚举....),
这些可迭代对象有一个共同的特征就是可以被for循环,而不能被for循环的都是不可迭代对象;
那么他们为什么可以被for循环呢?
Python种一切皆对象体现在+/-....语法都可以被Python解释隐藏调用一些双下(__add__。。。。)方法也就是已经被C语言实现好了的方法,当解释器遇到语法就会调用其对应的双下方法,进而返回结果;
顺腾摸瓜我们就来看一下这些可迭代对象中都隐藏了什么__共同的双下___方法;
ret=set(dir({})) & set(dir([])) & set(dir(()))
print(ret) {
'__reduce__', '__eq__', '__reduce_ex__', '__getitem__', '__len__', '__sizeof__', '__getattribute__', '__format__', '__subclasshook__', '__delattr__', '__gt__', '__setattr__', '__hash__', '__contains__', '__class__', '__iter__', '__doc__', '__le__', '__new__', '__init_subclass__', '__repr__', '__ge__', '__lt__', '__ne__', '__dir__', '__str__', '__init__' }
print('__iter__' in set(dir({}))) #可迭代对象拥有__iter__双下方法
print('__iter__' in set(dir(True))) #不可迭代对象没有__iter__双下方法
得知所有的可迭代对象内部都有1个__inter__()双下方法,这就是Python中规定的可迭代协议;
所以在for循环执行之前会去寻找循环对象的__inter__方法,如果没有__inter__方法,循环会直接报错,这是不可以迭代的对象;
l1=[1,2,3,4]
print(l1.__iter__())
所有可迭代对象执行__iter__双下方法之后都会返回1个迭代器
l1=[1,2,3,4]
print(set(dir(l1.__iter__())) - set(dir({}))) #{'__setstate__', '__next__', '__length_hint__'}
迭代器比可迭代对象多了3个双下方法分别是:__setstate__, __next__, __length_hint__
class A():
def __iter__():pass
def __next__():pass a=A() from collections import Iterable
from collections import Iterator print(isinstance(a,Iterable))#可迭代对象
print(isinstance(a,Iterator))#迭代器
迭代器协议:实现了__iter__ + __next__方法就是一个迭代器;
迭代器的作用:
1.由于可迭代对象生成数据是不会一下生成全部的数据,而是生成一个迭代器,然后1个1个得吐给你,所以就避免可生成大数据导致内存撑爆;
generater=range(10000000000000000000000000) #迭代器把数字1个1个得吐出来,不会占用1大块内存,而是随着for循环/__next__()1个1个得生成;
for n in generater: #随着for循环1个1个得取处迭代器中值
print(n) #big_data=list(range(10000000000000000000000000)) #会把数据1次生成,如果数据量过大,容易沾满内存
2.for循环是 对可迭代协议的实现
为啥列表/字典这些可迭代对象,没有__next__方法,容器中的元素也可以被 for循环出来呢?
因为for循环先执行了 [].__iter()__()把可迭代对象中__iter__()方法returen的结果组成 1个迭代器
然后1次1次得执行 [].__iter()__()__next__()把元素1个1个得获取出来。
#Python中for 循环的原理
list1=['','','','','']
g=list1.__iter__() #第1步:可迭代对象执行__iter__()得到1个生成器g
print(g.__next__()) #第2步:生成器g.__next__()遍历数据
print(g.__next__())
print(g.__next__())
print(g.__next__())
迭代器的应用场景
在平时写代码的过程中,需要产生大量的数据,但1次性全部生成又会导致内存占用量大,就可以使用迭代器协议,先生成迭代器,然后1个1个得吐出数据;
三、生成器
生成器的本质还是迭代器,可不过这个迭代器是程序员自己实现的;
实现生成器有2种方式:
方式1:yield写生成器函数
def func(): #普通函数
return 'zhanggen' ret=func()
print(ret)
------------------------------------------------------------------
def generator(): #0.生成器函数:函数内部包含yield关键字,就是生成器函数
yield 'zhang'
yield 'gen' g= generator() #1.生成器函数被调用后,得到1个生成器也就是迭代器作为返回值。
print(g.__next__()) #2.使用__next__()从里面取值
print(g.__next__())
使用生成器生成1000000个哇哈哈哈,只获取前50个
def wahaha():
for i in range(1000000):
yield "wahaha%s" %i g=wahaha()
print (g.__next__())#wahaha0 count=0 #获取前50个
for i in g:
count+=1
if count<=50:
print('for循环....%s'%i)
监听文件的输入,然后过滤用户输入的关键字
方式2:生成器表达式
g=(i for i in range(1,100)) print(g.__next__())
四、生成器进阶
send语法
send的作用和next类似,不同的是send可以在获取生成器函数里面 下1个yield 值的同时,还可以在上1个yield 值的右边send1个值到生成器函数里面。
def generator():
print(123)
num=yield 1 #Python解释器当遇到1个等号时 先执行右边的yield 1,然后赋值num=yield 1
print('send传入的值',num)
print(456)
num1=yield 2
print(num1)
yield 3
g=generator()
print(g.__next__()) #第一次调用生成器时不能使用 send
print(g.send('hello'))#send的效果和__next__效果一样
print(g.send('hello1'))#send的效果和__next__效果一样
print(g.__next__())#最后1次调用生成器不使用 send
使用send的注意事项:
综上所述send的功能,send不可以 第1次和最后1次调用生成器时使用。
如何让1个生成器,无限的yield值 ,不会遇到 StopIteration异常。
def average():
print('start')
num=0
while True:#下次调用 __next__依然在while循环里面
num+=4
yield num #4 8 12 16... g=average() print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
使用sen不断求平均值
#不断得计算平均值
def average():
sum_=0
count_=0
avg_=0
while True:
num_=yield avg_
sum_+=num_
count_+=1
print(sum_,num_,count_)
avg_=sum_/count_ avg_g=average()
avg_g.__next__()
print(avg_g.send(10))
print(avg_g.send(12))
print(avg_g.send(15))
print(avg_g.send(16))
yield from 语法
yield from 帮助我们从序列数据类型里1个1个得yield 出每1个元素,而不是使用 for 循环
def generator():
a='abcde'
b=''
yield a
yield b
'''
abcde
12345
'''
g=generator()
for i in g:
print(i) def generator():
a='abcde'
b=''
yield from a #帮助我们从序列数据类型里,1个1个yield 出每个元素,而不是使用 for 循环。
yield from b g=generator()
for i in g:
print(i) '''
a
b
c
d
e
1
2
3
4
5 '''
chain多个生成器
def coroutine1(n):
print('我这coroutine1里面')
yield ''
yield '' def coroutine2(n):
print('我这coroutine2里面')
yield ''
yield ''
def func(n):
print('我在func里面')
yield from coroutine1(n) #yield from 相当于1个中间件,可以在1个函数里面 直接 把其他生成器里所有yield的值获取到
yield from coroutine2(n) g=func(2)
print(next(g))
print(next(g))
print(next(g))
print(next(g)) '''
我这coroutine1里面
1
2
我这coroutine2里面
3
4
'''
Python之 反射、迭代器、生成器的更多相关文章
- python杂记-4(迭代器&生成器)
#!/usr/bin/env python# -*- coding: utf-8 -*-#1.迭代器&生成器#生成器#正确的方法是使用for循环,因为generator也是可迭代对象:g = ...
- python各种模块,迭代器,生成器
从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能) 本质就是.py结尾的python文件(文件名:test.py,对应的模块名就是test) 包:用来从逻辑上组织模块的,本质就是一个目 ...
- python基础6 迭代器 生成器
可迭代的:内部含有__iter__方法的数据类型叫可迭代的,也叫迭代对象实现了迭代协议的对象 运用dir()方法来测试一个数据类型是不是可迭代的的. 迭代器协议是指:对象需要提供next方法,它要么返 ...
- python中的迭代器&&生成器&&装饰器
迭代器iterator 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束. 迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外, ...
- Python入门之迭代器/生成器/yield的表达方式/面向过程编程
本章内容 迭代器 面向过程编程 一.什么是迭代 二.什么是迭代器 三.迭代器演示和举例 四.生成器yield基础 五.生成器yield的表达式形式 六.面向过程编程 ================= ...
- python中的迭代器 生成器 装饰器
什么迭代器呢?它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()(python2中实现next())方法的对象都是迭代器,_ ...
- Python函数系列-迭代器,生成器
一 迭代器 一 迭代的概念 #迭代器即迭代的工具,那什么是迭代呢?#迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 while True: #只是单纯地重复,因而不 ...
- Python学习 :迭代器&生成器
列表生成式 列表生成式的操作顺序: 1.先依次来读取元素 for x 2.对元素进行操作 x*x 3.赋予变量 Eg.列表生成式方式一 a = [x*x for x in range(10)] pri ...
- python第四周迭代器生成器序列化面向过程递归
第一节装饰器复习和知识储备------------ 第一节装饰器复习和知识储备------------ def wrapper(*args,**kwargs): index(*args,**kwa ...
- python装饰器,迭代器,生成器,协程
python装饰器[1] 首先先明白以下两点 #嵌套函数 def out1(): def inner1(): print(1234) inner1()#当没有加入inner时out()不会打印输出12 ...
随机推荐
- Delphi Label组件
- 《python解释器源码剖析》第0章--python的架构与编译python
本系列是以陈儒先生的<python源码剖析>为学习素材,所记录的学习内容.不同的是陈儒先生的<python源码剖析>所剖析的是python2.5,本系列对应的是python3. ...
- 格式化json扩展
json-handle 直接在chrome应用商店搜索JSON-handle或者去github搜索可用插件即可
- 详解thinkphp+redis+队列的实现代码
1,安装Redis,根据自己的PHP版本安装对应的redis扩展(此步骤简单的描述一下) 1.1,安装 php_igbinary.dll,php_redis.dll扩展此处需要注意你的php版本如图: ...
- 高可用,多路冗余GFS2集群文件系统搭建详解
高可用,多路冗余GFS2集群文件系统搭建详解 2014.06 标签:GFS2 multipath 集群文件系统 cmirror 实验拓扑图: 实验原理: 实验目的:通过RHCS集群套件搭建GFS2集群 ...
- [Atcoder2292] Division into Two
题目大意 给定n个不同的整数,求将它们分成两个集合X,Y,并且X集合中任意两个数的差>=A,Y集合中任意两个数的差>=B的方案数. 样例输入 5 3 7 1 3 6 9 12 样例输出 5 ...
- 在HTML中引入CSS的方式
有 4 种方式可以在 HTML 中引入 CSS.其中有 2 种方式是在 HTML 文件中直接添加 CSS 代码,另外两种是引入 外部 CSS 文件. ㈠内联方式 内联方式指的是直接在 HTML 标 ...
- jquery radio选择器 语法
jquery radio选择器 语法 作用::radio 选择器选取类型为 radio 的 <input> 元素.大理石平台价格表 语法:$(":radio") jqu ...
- ORACLE/SQL用函数进行每年,每月,每周,每日的数据汇总
15/03/21 用函数进行每年,每月,每周,每日的数据汇总 假设一个销售明细表 sale_detail 含有 国家(country),销售时间(sale_time),销售额(sale_money) ...
- UOJ #455 [UER #8]雪灾与外卖 (贪心、模拟费用流)
题目链接 http://uoj.ac/contest/47/problem/455 题解 模拟费用流,一个非常神奇的东西. 本题即为WC2019 laofu的讲课中的Problem 8,经典的老鼠进洞 ...