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 ...
随机推荐
- Mysql检查列是否存在并新增、修改、删除列
在MYSQL中,新增.修改.删除列时不能进行IF EXISTS判断,IF语句只能出现在存储过程当中,故博主用存储过程的方法新增.修改.删除列,修改列名称. DROP PROCEDURE IF EXIS ...
- Android图像处理之图形特效处理
一.Android变形矩阵——Matricx: 跟Android图像的色彩处理基本一样,只是将ColorMatrix换成了Matrix,ColorMatrix是4*5的矩阵,Matrix是3*3的.每 ...
- ES数据架构与关系数据库Mysql
ES数据架构的主要概念(与关系数据库Mysql对比) MySQL ElasticSearch Database Index Table Type Row Document Column Field S ...
- java 8 foreach获取索引
当 forEach 需要索引 https://segmentfault.com/a/1190000007881498 或者采用 List<string> stringList = new ...
- js 中dindexof()用法
https://www.cnblogs.com/jiadi321/p/10174317.html http://www.w3school.com.cn/jsref/jsref_splice.asp
- dlopen用法
1. 包含头文件 #include<dlfcn.h> 2. 函数定义 void * dlopen(const char* pathName, int mode); pathName 指的 ...
- Struts2基本原理【转】
阐述struts2的执行流程. Struts 2框架本身大致可以分为3个部分:核心控制器FilterDispatcher.业务控制器Action和用户实现的企业业务逻辑组件. 核心控制器FilterD ...
- sqlserver字段选择参照
SQL SERVER提供的说明. bit:0或1的整型数字 int:从-2^31(-2,147,483,648)到2^31(2,147,483,647)的整型数字 smallint:从-2^15( ...
- 【leetcode】1254. Number of Closed Islands
题目如下: Given a 2D grid consists of 0s (land) and 1s (water). An island is a maximal 4-directionally ...
- 几种最常见的js array操作方法及示例
1. 序言 操作array可谓前端最基础的工作,无论是从接口中取的数据,还是筛选数据,或者是添加按钮权限等等操作,array都是绕不开的东西.array的操作很多,初学者十分容易搞混,不是很熟练的情况 ...