Python编程学习笔记1.1

《Python编程》学习笔记1.1

礼物

本篇承接上文,介绍列表解析、生成器表达式和map的使用,这些都是python中的强大的迭代工具。

>>> pays = [person[2] for person in people]    # 收集薪酬信息
>>> pays
[36000.0, 60000.0]

>>> pays = map((lambda x: x[2]), people)   # 同上(map是3.x中的生成器)
>>> list(pays)
[36000.0, 60000.0]

>>> sum(person[2] for person in people)  # 生成器表达式,sum为内建函数
96000.0

列表解析式可以取代内建的map()函数以及lambda,而且效率更高。


列表解析介绍

它是根据已有列表,将之转换成另一个列表从而高效创建新列表的方式。

在转换过程中,可以指定元素必须符合一定的条件,才能添加至新的列表中,这样每个元素都可以按需要进行转换。

列表解析是Python迭代机制的一种应用,它常用于实现创建新的列表,因此用在[ ]中。

但它实际上是适用于任何可迭代对象的(iterable)。

List comprehension / Dict comprehension / Set comprehension / Generator comprehension

语法:

[expression for iter_val in iterable]

[expression for iter_val in iterable if cond_expr]

实例List comprehension:

要求:列出1~10所有数字的平方。

----------------------------------------------------
1、普通方法:
>>> L = []
>>> for i in range(1,11):
            L.append(i**2)
>>> print(L)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
----------------------------------------------------
2、列表解析
>>>L = [i**2 for i in range(1,11)]
>>>print L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

要求:列出1~10中大于等于4的数字的平方。

-----------------------------------------------------
1、普通方法:
>>> L = []
>>> for i in range(1,11):
             if i >= 4:
                  L.append(i**2)
>>> print(L)
[16, 25, 36, 49, 64, 81, 100]
-----------------------------------------------------
2、列表解析
>>>L = [i**2 for i in range(1,11) if i >= 4 ]
>>>print(L)
[16, 25, 36, 49, 64, 81, 100]

要求:实现两个列表中的元素逐一配对。

1、普通方法:
>>> L1 = ['x','y','z']
>>> L2 = [1,2,3]      
>>> L3 = []
>>> for a in L1:
             for b in L2:
                 L3.append((a,b))
>>> print(L3)
[('x', 1), ('x', 2), ('x', 3), ('y', 1), ('y', 2), ('y', 3), ('z', 1), ('z', 2), ('z', 3)]
-------------------------------------------------------------------------------------------
2、列表解析:
>>> L1 = ['x','y','z']
>>> L2 = [1,2,3]
>>> L3 = [ (a,b) for a in L1 for b in L2 ]
>>> print(L3)
[('x', 1), ('x', 2), ('x', 3), ('y', 1), ('y', 2), ('y', 3), ('z', 1), ('z', 2), ('z', 3)]

更多实例:Dict comprehension / Set comprehension / Generator comprehension

dict comprehension:
交换字典的key和value
>>> dt = {'A':1,'B':2}
>>> {value:key for key,value in dt.items()}
{1: 'A', 2: 'B'}
set comprehension:
>>> s = set([1,2,4])
>>> {i**i for i in s}
set([256, 1, 4])
generator comprehension:
>>> g = (a+2 for a in range(7))
>>> for i in g:
           print(i)
2
3
4
5
6
7
8

不足: 列表解析得一个不足就是必须生成所有数据,用于创建整个列表。这可能对有大量数据的迭代有其负面效应。
解决方法:生成器表达式,通过结合列表解析和生成器解决了这个问题。


生成器表达式

通过列表解析,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。

在Python中,这种一边循环一边计算的机制,称为生成器:generator。将之与列表解析结合就是生成器表达式了。

生成器表达式并不真正地创建数字列表,而是返回一个生成器对象,此对象在每次计算出一个条目后,把这个条目"产生"(yield)出来。生成器表达式使用了"惰性计算"或称作"延时求值"的机制。

一般来说,序列过长,并且每次只需要获取一个元素时,应该考虑生成器表达式而不是列表解析

语法:

(expression for iter_val in iterable)

(expression for iter_val in iterable if cond_expr)

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[ ]改成( ),就创建了一个generator。

实例:

>>> N = (i**2 for i in range(1,8))
>>> print(N)
 at 0x7fe4fd0e1c30>      #此处返回的是一个生成器的地址
>>> N.next()
1
>>> N.next()
4
>>> N.next()
9
>>> N.next()
16
>>> N.next()
25
>>> N.next()
36
>>> N.next()
49
>>> N.next()                #所有元素遍历完后,抛出异常StopIteration  
Traceback (most recent call last):
     File "", line 1, in 
StopIteration    

其他方法现在暂且不论。


迭代器

迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退

延迟计算或惰性求值 (Lazy evaluation)

迭代器不要求你事先准备好整个迭代过程中所有的元素。仅仅是在迭代至某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合。

可迭代对象

迭代器提供了一个统一的访问集合的接口。只要是实现了__iter__()__getitem__()方法的对象,就可以使用迭代器进行访问

  • 序列:字符串、列表、元组
  • 非序列:字典、文件
  • 自定义类:用户自定义的类实现了__iter__()__getitem__()方法的对象

创建迭代器对象

使用内建的工厂函数iter(iterable)可以获取迭代器对象:

语法:

iter(collection) -> iterator

iter(callable,sentinel) -> iterator

实例展示:

使用对象内置的__iter__()方法生成迭代器

>>>L1 = [1,2,3,4,5,6]
>>>I1 = L1.__iter__()
>>>print(I1)
   # 返回一个迭代器地址
>>> I1.next()
1
>>> I1.next()
2
>>> I1.next()
3

使用内置工厂函数生成迭代器

>>>L1 = [1,2,3,4,5,6]
>>>I1  = iter(L1)
>>>print(I1)
   # 返回一个迭代器地址
>>> I1.next()
1
>>> I1.next()
2
>>> I1.next()
3

说明:for循环可用于任何可迭代对象。
for循环开始时,会通过迭代协议传输给iter()内置函数,从而能够从迭代对象中获得一个迭代器,返回的对象含有需要的next()方法。

你可能感兴趣的:(Python编程学习笔记1.1)