Python 迭代器&生成器
1.内置参数
Built-in Functions | ||||
abs() | dict() | help() | min() | setattr() |
all() | dir() | hex() | next() | slice() |
any() | divmod() | id() | object() | sorted() |
ascii() | enumerate() | input() | oct() | staticmethod() |
bin() | eval() | int() | open() | str() |
bool() | exec() | isinstance() | ord() | sum() |
bytrarray() | filter() | issubclass() | pow() | super() |
bytes() | float() | iter() | print() | tuple() |
callable() | format() | len() | property() | type() |
chr() | frozenset() | list() | range() | vars() |
classmethod() | getattr() | locals() | repr() | zip() |
compile() | globals() | map() | reversed() | __import__() |
complex() | hasattr() | max() | round() | |
delattr() | hash() | memoryview() | set() |
内置参数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii
2.迭代器&生成器
列表生成式,是Python内置的一种极其强大的生成list的表达式。
如果要生成一个list [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9] 可以用 range(1 , 10):
1
2
|
#print(list(range(1,10))) [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] |
如果要生成[1x1, 2x2, 3x3, ..., 10x10]
怎么做?
1
2
3
4
5
6
|
l = [] for i in range ( 1 , 10 ): l.append(i * i) print (l) ####打印输出#### #[1, 4, 9, 16, 25, 36, 49, 64, 81] |
而列表生成式则可以用一行语句代替循环生成上面的list:
1
2
|
>>> print ([x * x for x in range ( 1 , 10 )]) [ 1 , 4 , 9 , 16 , 25 , 36 , 49 , 64 , 81 ] |
for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:
1
2
|
>>> print ([x * x for x in range ( 1 , 10 ) if x % 2 = = 0 ]) [ 4 , 16 , 36 , 64 ] |
- >>>[ i*2 for i in range(10)]
- [0,1,4,6,8,10,12,14,16,18]
- 等于
- >>>a=[]
- >>>for i in range(10):
- . . . a.append(i*2)
- >>>a
- [0,1,4,6,8,10,12,14,16,18]
小程序
- str1 = ""
- for i in iter(input,""): # 循环接收 input输入的内容
- str1 += i
- print(str1)
生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]
改成()
,就创建了一个generator:
- >>>l = [x*x for x in range(10)]
- >>>l
- [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
- >>>g = (x*x for x in range(10))
- >>>g
- <generator object <genexpr> at 0x1022ef630>
创建L
和g
的区别仅在于最外层的[]
和()
,L
是一个list,而g
是一个generator。
我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
如果要一个一个打印出来,可以通过next()
函数获得generator的下一个返回值:
- >>> next(g)
- 0
- >>> next(g)
- 1
- >>> next(g)
- 4
- >>> next(g)
- 9
- >>> next(g)
- 16
- >>> next(g)
- 25
- >>> next(g)
- 36
- >>> next(g)
- 49
- >>> next(g)
- 64
- >>> next(g)
- 81
- >>> next(g)
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- StopIteration
所以,我们创建了一个generator后,基本上永远不会调用next()
,而是通过for
循环来迭代它,并且不需要关心StopIteration
的错误。
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for
循环无法实现的时候,还可以用函数来实现。
比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
- def fib(max):
- n,a,b=0,0,1
- while n < max:
- print(b)
- a,b=b,a+b
- n = n+1
- return 'done'
上面的函数可以输出斐波那契数列的前N个数:
- >>>fib(10)
- 1
- 1
- 2
- 3
- 5
- 8
- 13
- 21
- 34
- 55
- done
生成器的特点:
1)生成器只有在调用时才会生成相应的数据;
2)只记录当前位置;
3)只有一个__next__()方法;
还可通过yield实现在单线程的情况下实现并发运算的效果:
- import time
- def consumer(name):
- print("%s 准备吃包子!" %name)
- while True:
- baozi = yield
- print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
- c = consumer("ChenRonghua")
- c.__next__()
- def produceer(name):
- c = consumer("a")
- c2 = consumer("b")
- c.__next__()
- c2.__next__()
- print("老子开始准备做包子啦!")
- for i in range(10):
- time.sleep(1)
- print("做了1个包子,分两半!")
- c.send(i)
- c2.send(i)
- produceer("alex")
迭代器
我们已经知道,可以直接作用于for
循环的数据类型有以下几种:
一类是集合数据类型,如list
、tuple
、dict
、set
、str
等;
一类是generator
,包括生成器和带yield
的generator function。
这些可以直接作用于for
循环的对象统称为可迭代对象:Iterable
。
可以使用isinstance()
判断一个对象是否是Iterable
对象:
- >>>from collections import Iterable
- >>>isinstance([],Iterable)
- True
- >>>isinstance({},Iterable)
- True
- >>>isinstance('abc',Iterable)
- True
- >>> isinstance((x for x in range(10)), Iterable)
- True
- >>> isinstance(100, Iterable)
- False
凡是可作用于for
循环的对象都是Iterable
类型;
凡是可作用于next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。
Python的for
循环本质上就是通过不断调用next()
函数实现的,例如:
- for x in [1,2,3,4,5]:
- pass
实际上完全等价于:
- # 首先获得Iterator对象:
- it = iter([1, 2, 3, 4, 5])
- # 循环:
- while True:
- try:
- # 获得下一个值:
- x = next(it)
- except StopIteration:
- # 遇到StopIteration就退出循环
- break
3.Json&pickle数据序列化
用于序列化的两个模块
- json,用于字符串 和 python数据类型间进行转换
- pickle,用于python特有的类型 和 python的数据类型间进行转换
Json模块提供了四个功能:dumps、dump、loads、load
pickle模块提供了四个功能:dumps、dump、loads、load
- info = {
- "name":"alex",
- "age":22
- }
- f = open("test.txt","w")
- f.write(info)
- f.close()
json序列化
- f = open("test.txt","r")
- data = eval(f.read())
- f.close()
- print(data['age'])
json反序列化
json能处理简单的数据类型,字典,列表,字符串。
json是所有语言通用的,json的作用是不同语言之间进行数据交互。
- #json序列化
- import json
- info = {
- "name":"alex",
- "age":22
- }
- f = open("test.txt","w")
- #print(json.dumps(info))
- f.write(json.dumps(info))
- f.close()
- #json反序列化
- import json
- f = open("test.txt","r")
- data = json.loads(f.read())
- f.close()
- print(data['age'])
json序列化,反序列化
- import pickle
- def sayhi(name):
- print("hello,",name)
- info = {
- "name":"alex",
- "age":22,
- "func":sayhi
- }
- f = open("test.txt","wb")
- f.write(pickle.dumps(info))
- f.close()
pickle序列化
- import pickle
- def sayhi(name):
- print("hello,",name)
- f = open("test.txt","rb")
- data = pickle.loads(f.read())
- print(data['func']("Alex"))
pickle反序列化
4.装饰器
定义:
本质上是个函数,功能是装饰其他函数—就是为其他函数添加附加功能
装饰器原则:
1) 不能修改被装饰函数的源代码;
2) 不能修改被装饰函数的调用方式;
实现装饰器知识储备:
函数即“变量”
定义一个函数相当于把函数体赋值给了函数名
1.函数调用顺序:其他高级语言类似,python不允许在函数未声明之前,对其进行引用或者调用
错误示范:
- def foo():
- print('in the foo')
- bar()
- foo()
- 报错:
- in the foo
- Traceback (most recent call last):
- File "<pyshell#13>", line 1, in <module>
- foo()
- File "<pyshell#12>", line 3, in foo
- bar()
- NameError: global name 'bar' is not defined
- def foo():
- print('foo')
- bar()
- foo()
- def bar()
- print('bar')
- 报错:NameError: global name 'bar' is not defined
正确示范:(注意,python为解释执行,函数foo在调用前已经声明了bar和foo,所以bar和foo无顺序之分)
- def foo()
- print('in the foo')
- bar()
- def bar():
- print('in the bar')
- foo()
- def bar():
- print('in the bar')
- def foo():
- print('in the foo')
- bar()
- foo()
2.高阶函数
满足下列条件之一就可成函数为高阶函数
1.某一函数当做参数传入另一个函数中
2.函数的返回值包含n个函数,n>0
高阶函数示范:
- def bar():
- print('in the bar')
- def foo(func):
- res=func()
- return res
- foo(bar)
高阶函数的牛逼之处:
- def foo(func):
- return func
- print('function body is %s' %(foo(bar)))
- print('function name is %s' %(foo(bar).func_name))
- foo(bar)()
- #foo(bar)() 等同于bar=foo(bar)然后bar()
- bar = foo(bar)
- bar()
3.内嵌函数和变量作用域
定义:在一个函数体内创建另一个函数,这种函数就叫内嵌函数
嵌套函数:
- def foo():
- def bar():
- print('in the bar')
- bar()
- foo()
局部作用域和全局做用域的访问顺序
- x = 0
- def grandpa():
- def dad():
- x = 2
- def son():
- x=3
- print(x)
- son()
- dad()
- grandpa()
4.高阶函数+内嵌函数=》装饰器
函数参数固定
- def decorartor(func):
- def wrapper(n):
- print('starting')
- func(n)
- print('stopping')
- return wrapper
- def test(n):
- print('in the test arg is %s' %n)
- decorartor(test)('alex')
函数参数不固定
- def decorartor(func):
- def wrapper(*args,**kwargs):
- print('starting')
- func(*args,**kwargs)
- print('stopping')
- return wrapper
- def test(n,x=1):
- print('in the test arg is %s' %n)
- decorartor(test)('alex',x=2222)
1.无参装饰器
- import time
- def decorator(func):
- def wrapper(*args,**kwargs):
- start_time=time.time()
- func(*args,**kwargs)
- stop_time=time.time()
- print("%s" %(stop_time-start_time))
- return wrapper
- @decorator
- def test(list_test):
- for i in list_test:
- time.sleep(0.1)
- print('-'*20,i)
- #decorator(test)(range(10))
- test(range(10))
2.有参装饰器
- import time
- def timer(timeout=0):
- def decorator(func):
- def wrapper(*args,**kwargs):
- start=time.time()
- func(*args,**kwargs)
- stop=time.time()
- print('run time is %s ' %(stop-start))
- print(timeout)
- return wrapper
- return decorator
- @timer(2)
- def test(list_test):
- for i in list_test:
- time.sleep(0.1)
- print ('-'*20,i)
- #timer(timeout=10)(test)(range(10))
- test(range(10))
3.终极装饰器
- user,passwd = 'alex','abc123'
- def auth(auth_type):
- print('auth func:',auth_type)
- def outer_wrapper(func):
- def wrapper(*args,**kwargs):
- print("wrapper func args:",*args,**kwargs)
- if auth_type=="local":
- username = input("Username:").strip()
- password = input("Password:").strip()
- if user == username and passwd == password:
- res = func(*args,**kwargs)
- print("---after authentication")
- return res
- else:
- exit("\033[31;1mInvalid username or password\033[0m")
- elif auth_type == "ldap":
- print('搞毛线ldap,不会......')
- return wrapper
- return outer_wrapper
- def index():
- print("welcome to index page")
- @auth(auth_type="local") #home = wrapper()
- def home():
- print("welcome to home page")
- return "from home"
- @auth(auth_type="ldap")
- def bbs():
- print("welcome to bbs page")
- index()
- print(home())#wrapper()
- bbs()
Python 迭代器&生成器的更多相关文章
- Python迭代器生成器与生成式
Python迭代器生成器与生成式 什么是迭代 迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果.每一次对过程的重复称为一次"迭代",而每一次迭代得到的结果会作为下一次迭 ...
- python 迭代器 生成器
迭代器 生成器 一 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前 ...
- Python 迭代器&生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发
本节大纲 迭代器&生成器 装饰器 基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - ...
- python迭代器,生成器,推导式
可迭代对象 字面意思分析:可以重复的迭代的实实在在的东西. list,dict(keys(),values(),items()),tuple,str,set,range, 文件句柄(待定) 专业角度: ...
- 4.python迭代器生成器装饰器
容器(container) 容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中.通常这类数据结构把所有的元素存储在内存中 ...
- python迭代器生成器
1.生成器和迭代器.含有yield的特殊函数为生成器.可以被for循环的称之为可以迭代的.而可以通过_next()_调用,并且可以不断返回值的称之为迭代器 2.yield简单的生成器 #迭代器简单的使 ...
- Python迭代器生成器,私有变量及列表字典集合推导式(二)
1 python自省机制 这个是python一大特性,自省就是面向对象的语言所写的程序在运行时,能知道对象的类型,换句话说就是在运行时能获取对象的类型,比如通过 type(),dir(),getatt ...
- Python迭代器生成器,模块和包
1.迭代器和生成器 2.模块和包 1.迭代器 迭代器对象要求支持迭代器协议的对象,在Python中,支持迭代器协议就是实现对象的__iter__()和__next__()方法. 其中__it ...
- python迭代器生成器-迭代器和list区别
迭代 生成 for循环遍历的原理 for循环遍历的原理就是迭代,in后面必须是可迭代对象 为什么要有迭代器 对于序列类型:字符串.列表.元组,我们可以使用索引的方式迭代取出其包含的元素.但对于字典.集 ...
随机推荐
- BZOJ1110: [POI2007]砝码Odw
Description 在byteotian公司搬家的时候,他们发现他们的大量的精密砝码的搬运是一件恼人的工作.公司有一些固定容量的容器可以装这些砝码.他们想装尽量多的砝码以便搬运,并且丢弃剩下的砝码 ...
- Solr资料
Apache Solr Reference GuideCovering Apache Solr 5.5 https://archive.apache.org/dist/lucene/solr/ref- ...
- js根据浏览器窗口大小实时改变网页文字大小
目前,有了css3的rem,给我们的移动端开发带来了前所未有的改变,使得我们的开发更容易,更易兼容很多设备,但这个不在本文讨论的重点中,本文重点说说如何使用js来实时改变网页文字的大小. 代码: &l ...
- [CareerCup] 18.4 Count Number of Two 统计数字2的个数
18.4 Write a method to count the number of 2s between 0 and n. 这道题给了我们一个整数n,让我们求[0,n]区间内所有2出现的个数,比如如 ...
- [CareerCup] 15.7 Student Grade 学生成绩
15.7 Imagine a simple database storing information for students' grades. Design what this database m ...
- java.lang.String
1.String 是一个类,广泛应用于 Java 程序中,相当于一系列的字符串.在 Java 语言中 strings are objects.创建一个 strings 最直接的方式是 String g ...
- 伪类link,hover,active,visited,focus的区别
例一: /*css*/a:link{ color: blue;}a:visited{ color: green;}a:hover{ color: red;}a:focus{ color:blac ...
- jq最新前三篇文章高亮显示
/*---------最新前三篇文章高亮显示-------------*/ function latest(){ var color_arr=new Array( "blue", ...
- Jquery dialog属性
修改标题: $('#test').dialog("option","title", "测试").dialog('open'); 修改位置: ...
- BizTalk开发系列(十五) Schema设计之Qualified 与Unqualified
XML Schema中的命名空间前缀限定包括对元素(Element)或属性(Attribute)的限定,即常见的如 “<ns0:root>...</ns0:root>”之类的格 ...