容器是一种把多个元素组织在一起的数据结构, 容器中的元素可以逐个地迭代获取, 可以用 in, not in 关键字判断元素是否包含在容器中. 通常这类数据结构把所有的元素存储在内存中 (也有一些特例, 并不是所有的元素都放在内存, 比如迭代器和生成器对象) 在 Python 中, 常见的容器对象有:
list, deque, ....
set, frozensets, ....
dict, defaultdict, OrderedDict, Counter, ....
tuple, namedtuple, ...
str
容器比较容易理解, 因为你就可以把它看作是一个盒子, 一栋房子, 一个柜子, 里面可以塞任何东西. 从技术角度来说, 当它可以用来询问某个元素是否包含在其中时, 那么这个对象就可以认为是一个容器, 比如 list,set,tuples 都是容器对象.
2. 可迭代对象(iterable)
凡是可以返回一个迭代器的对象都可称之为可迭代对象
3. 迭代器(iterator)
那么什么迭代器呢? 它是一个带状态的对象, 他能在你调用 next()方法的时候返回容器中的下一个值, 任何实现了__iter__和__next__()方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一个值, 如果容器中没有更多元素了, 则抛出 StopIteration 异常, 至于它们到底是如何实现的这并不重要.
4. 生成器(generator)
一个包含了 yield 关键字的函数就是一个生成器, 该函数也叫生成器函数. 当生成器函数被调用时, 在函数体中的代码不会被执行, 而会返回一个迭代器. 每次请求一个值, 就会执行生成器中代码, 直到遇到一个 yield 表达式或 return 语句. yield 表达式表示要生成一个值, return 语句表示要停止生成器. 换句话说, 生成器是由两部分组成, 生成器的函数和生成器的迭代器. 生成器的函数是用 def 语句定义的, 包含 yield 部分; 生成器的迭代器是这个函数返回的部分. 二者合起来叫做生成器.
迭代器与生成器
1. 迭代器使用举例
- city = ['beijing','shanghai','tinajin','chongqin']
- it = iter(city)
- print(type(it))
- # 方法一: 使用 next 方法来使用迭代器
- print(it.__next__())
- print(it.__next__())
方法二: 使用 for 循环来使用迭代器
- for x in it:
- print(x)
2. 生成器函数完成与 counter 类似功能
- def generator(low,high):
- while low <= high:
- yield low
- low += 1
- for i in generator(1,10):
- print(i,end='')
结果: 12345678910
3. 生成器产生无限多的值
- def generator(start = 0):
- while True:
- yield start
- start += 1
- for number in generator(4):
- print(number,end='')
- if number> 20:
- break
4. 列表生成器
- a = [i*2 for i in range(1,10)]
- print(a)
结果:
[2, 4, 6, 8, 10, 12, 14, 16, 18]
装饰器
要求:
不能修改被装饰的函数的源代码
不能修改被装饰的函数的调用方式
满足上面的两种情况下给程序增添功能
组成:
<函数 + 实参高阶函数 + 返回值高阶函数 + 嵌套函数 + 语法糖 = 装饰器>
1. 简单装饰器
- import time
- def timer(func):
- def wrapper():
- start_time = time.time()
- func()
- stop_time = time.time()
- print("run time %s"%(stop_time-start_time))
- return wrapper
- @timer #语法糖 test=timer(test)
- def test():
- time.sleep(3)
- print("in the test")
- test()
15 结果:
- in the test
- run time 3.000171661376953.
1.test 表示的是函数的内存地址
2.test()就是调用对在 test 这个地址的内容, 即函数
高阶函数:
1. 把一个函数名当作实参传给另外一个函数("实参高阶函数")
2. 返回值中包含函数名("返回值高阶函数")
这里面所说的函数名, 实际上就是函数的地址, 把函数名当做实参, 那么也就是说可以把函数传递到另一个函数, 然后在另一个函数里面做一些操作.
嵌套函数:
嵌套函数指的是在函数内部定义一个函数, 而不是调用
函数只能调用和它同级别以及上级的变量或函数. 也就是说: 里面的能调用和它缩进一样的和他外部的, 而内部的是无法调用的.
把 test 作为参数传递给了 timer(), 此时, 在 timer()内部, func = test, 接下来, 定义了一个 wrapper()函数, 但并未调用, 只是在内存中保存了, 并且
标签为 wrapper. 在 timer()函数的最后返回 wrapper()的地址 wrapper. 然后再把 wrapper 赋值给了 test, 那么此时 test 已经不是原来的 test 了, 也就是 test 原来的那些函数体的标签换掉了, 换成了 wrapper
2. 装饰有参函数
- import time
- def timer(func):
- def deco(*args,**kwargs):
- start_time = time.time()
- func(*args,**kwargs)
- stop_time = time.time()
- print(stop_time-start_time)
- return deco
- @timer
- def test(parameter):
- time.sleep(3)
- print("test is running")
- test("添加参数")
3. 更复杂的装饰器
对这两个函数分别统计运行时间, 再加一层函数来接受参数, 根据嵌套函数的概念, 要想执行内函数, 就要先执行外函数, 才能调用到内函数
- import time
- def timer(parameter):
- def outer_wrapper(func):
- def wrapper(*args, **kwargs):
- if parameter == 'task1':
- start = time.time()
- func(*args, **kwargs)
- stop = time.time()
- print("the task1 run time is :", stop - start)
- elif parameter == 'task2':
- start = time.time()
- func(*args, **kwargs)
- stop = time.time()
- print("the task2 run time is :", stop - start)
- return wrapper
- return outer_wrapper
- @timer(parameter='task1')
- def task1():
- time.sleep(2)
- print("in the task1")
- @timer(parameter='task2')
- def task2():
- time.sleep(2)
- print("in the task2")
- task1()
- task2()
来源: http://www.bubuko.com/infodetail-2959785.html