1.assert:python assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常。
2.
容器(container)
容器是一种把多个元素组织在一起的数据结构,
容器中的元素可以逐个地迭代获取,
可以用in
, not in
关键字判断元素是否包含在容器中。
通常这类数据结构把所有的元素存储在内存中
(也有一些特例,并不是所有的元素都放在内存,比如迭代器和生成器对象)在Python中,常见的容器对象有:
- list, deque, ....
- set, frozensets, ....
- dict, defaultdict, OrderedDict, Counter, ....
- tuple, namedtuple, …
- str
容器比较容易理解,因为你就可以把它看作是一个盒子、一栋房子、一个柜子,里面可以塞任何东西。
从技术角度来说,当它可以用来询问某个元素是否包含在其中时,那么这个对象就可以认为是一个容器,
比如 list,set,tuples都是容器对象:
d = {1: 'foo', 2: 'bar', 3: 'qux'}
assert 1 in d
尽管绝大多数容器都提供了某种方式来获取其中的每一个元素,
但这并不是容器本身提供的能力,而是可迭代对象赋予了容器这种能力,
当然并不是所有的容器都是可迭代的,比如:Bloom filter,
虽然Bloom filter可以用来检测某个元素是否包含在容器中,但是并不能从容器中获取其中的每一个值,
因为Bloom filter压根就没把元素存储在容器中,而是通过一个散列函数映射成一个值保存在数组中。
可迭代对象(iterable)
>>> x = [1, 2, 3] >>> y = iter(x) >>> z = iter(x) >>> next(y) 1 >>> next(y) 2 >>> next(z) 1 >>> type(x) <class 'list'> >>> type(y) <class 'list_iterator'>
这里x
是一个可迭代对象,可迭代对象和容器一样是一种通俗的叫法,
并不是指某种具体的数据类型,list是可迭代对象,dict是可迭代对象,
set也是可迭代对象。y
和z
是两个独立的迭代器,迭代器内部持有一个状态,
该状态用于记录当前迭代所在的位置,以方便下次迭代的时候获取正确的元素。
迭代器有一种具体的迭代器类型,比如list_iterator
,set_iterator
。
可迭代对象实现了__iter__
方法,该方法返回一个迭代器对象。
迭代器(iterator)
那么什么迭代器呢?它是一个带状态的对象,他能在你调用next()
方法的时候返回容器中的下一个值,
任何实现了__iter__
和__next__()
(python2中实现next()
)方法的对象都是迭代器,
__iter__
返回迭代器自身,__next__
返回容器中的下一个值,如果容器中没有更多元素了,
则抛出StopIteration异常,至于它们到底是如何实现的这并不重要。
所以,迭代器就是实现了工厂模式的对象,它在你每次你询问要下一个值的时候给你返回。
有很多关于迭代器的例子,比如itertools
函数返回的都是迭代器对象。
生成器(generator)
生成器算得上是Python语言中最吸引人的特性之一,
生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。
它不需要再像上面的类一样写__iter__()
和__next__()
方法了,
只需要一个yiled
关键字。 生成器一定是迭代器(反之不成立),
因此任何生成器也是以一种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是: