Python - 三大器 迭代器,生层器,装饰器

在介绍三大器之前先来了解一下容器和可迭代对象...

一. 容器

容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中。通常这类数据结构把所有的元素存储在内存中(也有一些特例,并不是所有的元素都放在内存,比如迭代器和生成器对象)在Python中,常见的容器对象有:

  • list, deque...
  • set, frozensets(不可变集合)...
  • dict, defaultdict, OrderedDict, Counter...
  • tuple, namedtuple...
  • str

容器的概念就像一个盒子,可以往里面装东西.当它可以用来询问某个元素是否包含在其中时,那么这个对象就可以认为是一个容器,比如 list,set,tuples都是容器对象:

>>> assert 1 in [1, 2, 3]      # lists
>>> assert 4 not in [1, 2, 3]
>>> assert 1 in {1, 2, 3} # sets
>>> assert 4 not in {1, 2, 3}
>>> assert 1 in (1, 2, 3) # tuples
>>> assert 4 not in (1, 2, 3)

询问某元素是否在dict中用dict的中key:

>>> d = {1: 'foo', 2: 'bar', 3: 'qux'}
>>> assert 1 in d
>>> assert 'foo' not in d # 'foo' 不是dict中的元素

询问某substring是否在string中:

>>> s = 'foobar'
>>> assert 'b' in s
>>> assert 'x' not in s
>>> assert 'foo' in s

尽管绝大多数容器都提供了某种方式来获取其中的每一个元素,但这并不是容器本身提供的能力,而是可迭代对象赋予了容器这种能力,当然并不是所有的容器都是可迭代的,比如:Bloom filter,虽然Bloom filter可以用来检测某个元素是否包含在容器中,但是并不能从容器中获取其中的每一个值,因为Bloom filter压根就没把元素存储在容器中,而是通过一个散列函数映射成一个值保存在数组中。

二. 可迭代对象(iterable)

大部分对象都是可迭代,只要实现了__iter__方法的对象就是可迭代的。

__iter__方法会返回迭代器(iterator)本身,例如:

>>> lst = [1,2,3]
>>> lst.__iter__()
<listiterator object at 0x7f97c549aa50>

Python提供一些语句和关键字用于访问可迭代对象的元素,比如for循环、列表解析、逻辑操作符等。

判断一个对象是否是可迭代对象:

>>> from collections import Iterable  # 只导入Iterable方法
>>> isinstance('abc', Iterable)
True
>>> isinstance(1, Iterable)
False
>>> isinstance([], Iterable)
True

这里的isinstance()函数用于判断对象类型。

可迭代对象一般都用for循环遍历元素,也就是能用for循环的对象都可称为可迭代对象。

例如,遍历列表:

>>> lst = [1, 2, 3]
>>> for i in lst:
... print i
...

三. 迭代器

迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stoplteration异常,以终止迭代(只能往后走不能往前退)

实现了迭代器协议的对象(对象内部定义了一个__iter__()方法)

python中的内部工具(如for循环,sum,min,max函数等)基于迭代器协议访问对象。

使用迭代器的好处:

1)如果使用列表,计算值时会一次获取所有值,那么就会占用更多的内存。而迭代器则是一个接一个计算。

2)使代码更通用、更简单。

判断是否是迭代器:

>>> from collections import Iterator
>>> isinstance(d, Iterator)
False
>>> isinstance(d.iteritems(), Iterator)
True

使用next方法:

>>> iter_items = d.iteritems()
>>> iter_items.next()
('a', 1)
>>> iter_items.next()
('c', 3)
>>> iter_items.next()
('b', 2)

迭代器的原理:

1 #基于迭代器协议
2 li = [1,2,3]
3 diedai_l = li.__iter__()
4 print(diedai_l.__next__())
5 print(diedai_l.__next__())
6 print(diedai_l.__next__())
7 # print(diedai_l.__next__()) # 超出边界报错
8
9 #下标
10 print(li[0])
11 print(li[1])
12 print(li[2])
13 # print(li[3]) # 超出边境报错
14
15 # 用while循环模拟for循环机制
16 diedai_l = li.__iter__()
17 while True:
18 try:
19 print(diedai_l.__next__())
20 except StopIteration:
21 print("迭代完毕,循环终止")
22 break
23
24 # for循环访问方式
25 # for循环本质就是遵循迭代器协议的访问方式,先调用diedai_l=li.__iter__方法
26 # 或者直接diedai_l=iter(l),然后依次执行diedai_l.__next__(),直到捕捉到
27 # StopItearation终止循环
28 # for循环所有的对象的本质都是一样的原理

四. 生成器

可以理解为一种数据类型,自动实现迭代器协议

  在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行next()方法时从当前位置继续运行

  1. 表现形式:

    生成器函数 带yield的函数(1、返回值 2、保留函数的运行状态)

          next(t)  t.__next__  t.send(可以给上一层的yield传值)

     # 用生成器函数
    # yield 相当于return控制的是函数的返回值
    # x=yield的另外一个特性,接收send传过来的值,赋值给x
    def test():
    print("开始啦")
    first = yield # return 1 first = None
    print("第一次",first)
    yield 2
    print("第二次")
    t = test()
    print(test().__next__())
    res = t.__next__() # next(t)
    print(res)
    res = t.send("函数停留在first那个位置,我就是给first赋值的")
    print(res) 输出结果
    开始啦
    None
    开始啦
    None
    第一次 函数停留在first那个位置,我就是给first赋值的
  2. 生成器表达式

    print(sum(i for i in range(10000))) # 表达式一般用for循环 (i for i in range(10000))

    作用 节省内存,在内部已经实现了__iter__的方法

五. 装饰器

1. 定义

在不修改被修饰函数的源代码和调用方式的情况下给其添加额外功能.

装饰器 = 高阶函数+函数嵌套+闭包

import time #导入时间模块

def foo(func):	# func = test
def bar(*args,**kwargs):
start_time = time.time()
res = func(*args,**kwargs) # 这里就是在运行test() 赋予变量
stop_time = time.tiem()
print("一场LOL时间为{}").format(stop_time-start_time)
return res # 返回test()的值
return bar def test(name, age):
time.sleep(1)
print("哈哈")
return "heihei" res = test("德玛西亚", age=10)
print(ret)

六. 闭包

根据这句话,其实我们自己就可以总结出在python语言中形成闭包的三个条件,缺一不可:

1)必须有一个内嵌函数(函数里定义的函数)——这对应函数之间的嵌套

2)内嵌函数必须引用一个定义在闭合范围内(外部函数里)的变量——内部函数引用外部变量

3)外部函数必须返回内嵌函数——必须返回那个内部函数

def funx():
x=5
def funy():
nonlocal x
x+=1
return x
return funy

python闭包的优点:

避免使用全局变量

可以提供部分数据的隐藏

可以提供更优雅的面向对象实现

Python - 三大器 迭代器,生层器,装饰器的更多相关文章

  1. 详解python三大器——迭代器、生成器、装饰器

    迭代器 聊迭代器前我们要先清楚迭代的概念:通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值). 可迭代对象(i ...

  2. Python 闭包、迭代器、生成器、装饰器

    Python 闭包.迭代器.生成器.装饰器 一.闭包 闭包:闭包就是内层函数对外层函数局部变量的引用. def func(): a = "哈哈" def func2(): prin ...

  3. python is、==区别;with;gil;python中tuple和list的区别;Python 中的迭代器、生成器、装饰器

    1. is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同 == 比较的是两个对象的内容是否相等 2. with语句时用于对try except finally 的优 ...

  4. python 生成器,迭代器,闭包,装饰器

    1.生成器,迭代器,闭包,装饰器的优点 生成器就是一类特殊的迭代器 迭代器的优点也即生成器的优点: 1.节约内存.python在使用生成器时对延迟操作提供了支持. 2.迭代到下一次的调用时,所使用的参 ...

  5. python基础之迭代器、生成器、装饰器

    一.列表生成式 a = [0,1,2,3,4,5,6,7,8,9] b = [] for i in a: b.append(i+1) print(b) a = b print(a) --------- ...

  6. python基础知识---迭代器、生成器、装饰器

    一.迭代器 二.生成器 http://www.cnblogs.com/huxi/archive/2011/07/14/2106863.html def func(): #定义生成器,和普通函数的区别是 ...

  7. Python学习(三):迭代器、生成器、装饰器、递归、算法、正则

    1.迭代器 迭代器是访问集合的一种方式,迭代对象从集合的第一个元素开始访问,直到元素被访问结束,迭代器只能往前不能后退,最大的优点是不要求事先准备好整个迭代过程中的元素,这个特点使得它特别适合用于遍历 ...

  8. Python开发——7.迭代器、生成器和装饰器

    一.迭代器 1.迭代器协议 (1)迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么引起一个StopIteration移除异常以中止迭代. (2)可迭代对象:实现了迭 ...

  9. Python基础4 迭代器,生成器,装饰器,Json和pickle 数据序列化

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需 ...

随机推荐

  1. 安卓dex 文件结构简要说明

    #ifndef _DEX_FILE_HELPER_ #define _DEX_FILE_HELPER_ //此文件仅仅是起帮助作用,帮助不太了解DexFile结构的了解一下DexFile相关结构,想更 ...

  2. 面向画布(Canvas)的JavaScript库

    面向画布(Canvas)的JavaScript库 总结 每个库各有特色,根据需求选择   学习要点 面向画布(Canvas)的JavaScript库 EaselJS 是一个封装了 HTML5 画布(C ...

  3. Java 下的函数对象

    1. 举例 如我们要创建一个对大小写敏感的,按照字母序排序的 Set,我们需要向 Set 的构造器传入 String.CASE_INSENTIVE_ORDER 的比较器: Set<String& ...

  4. Fy's dota2

    Fy 觉得自己玩 cf,lol 这种高端游戏已经够厉害了,于 是他决定去玩 dota2.结果 fy 的鼠标右键坏了,所以他就等 到 2250 买了把闪烁匕首,用跳刀前进,准备去送泉水.但 是 fy 一 ...

  5. [Swift通天遁地]三、手势与图表-(10)创建包含圆点、方形、三角形图标的散点图表

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  6. 接口管理功能全面增强!EOLINKER EPC 5.0.9版本更新:支持LDAP用户系统、加入更多项目统计图表、强化测试/自动化测试功能等

    EOLINKER EPC(Enterprise Private Cloud 企业私有云产品)已于近期发布5.0.9版本:界面全面改版.支持LDAP用户系统.加入更多项目统计图表.强化测试/自动化测试功 ...

  7. $ST表刷题记录$

    \(st表的题目不太多\) 我做过的就这些吧. https://www.luogu.org/problemnew/show/P3865 https://www.luogu.org/problemnew ...

  8. ACM_统计字符串

    统计字符串 Time Limit: 2000/1000ms (Java/Others) Problem Description: 给定n个字符串,统计字符串的个数. 如给定 5 sss ab sss ...

  9. 修改docker-toolbox/boot2docker容器镜像

    进入虚拟机 vi /var/lib/boot2docker/profile 编辑在EXTRA_ARGS,加入 --registry-mirror=https://pee6w651.mirror.ali ...

  10. C# Nugut CsvHelper 使用

    装载自: 跳转链接>>>