第三章Python解析list,dictionary,set

一些前提

os module
import os
os.getcwd()获得当前工作目录
os.chdir()改变当前工作目录
os.path 模块包含了操作文件名和目录名的函数
os.path.join() 函数从一个或多个路径片段中构造一个路径名
os.path.expanduser() 用来将包含~符号(表示当前用户Home目录)的路径扩展为完整的路径。在任何有Home 目录概念的操作系统上(包括Linux,Mac OS X 和Windows),这个函数都能工作。返回的路径不以斜杠结尾,但是os.path.join()并不介意这一点。
os.path.split() 函数正是这样做的。 将split函数的返回值赋值给一个二元组。每个变量获得了返回元组中的对应元素的值
os.stat() 函数返回一个包含多种文件元信息的对象


glob module
import glob
glob.glob() 函数返回一个相对路径的列表

time module
import time
time模块是Python标准库的一部分。 它包含用于在不同时间格式中转换,将时间格式化成字符串以及处理时区的函数。
time.localtime() 函数将从纪元到现在的秒数这个格式表示的时间函数返回值的属性转换成更有用的包含年、月、日、小时、分钟、秒的结构体。这个文件的最后修改时间是2009年7月13日下午5:25。
 

解析List

列表解析提供了一种紧凑的方式,实现了通过对列表中每一个元素应用一个函数的方法来将一个列表映射到另一个列表.

>>> a_list = [1, 9, 8, 4]
>>> [elem * 2 for elem in a_list] ①
[2, 18, 16, 8]
>>> a_list ②
[1, 9, 8, 4]
>>> a_list = [elem * 2 for elem in a_list] ③
>>> a_list
[2, 18, 16, 8]
为了理解这一点,请从右向左看。 a_list是你要映射的列表。Python解释器逐个访问a_list的元素,并临时将元素赋值给变量elem。 然后Python 对元素应用函数elem* 2并且将结果添加到返回列表中。
列表解析创造一个新的列表而不改变原列表。
可以安全的将列表解析的结果赋值给被映射的变量。Python会在内存中构造新的列表,在列表解析完成后将结果赋值给原来的变量。

可以在列表解析中使用任何的Python表达式, 包括os 模块中用于操作文件和目录的函数。

>>> import os, glob
>>> glob.glob('*.xml') ①
['feed-broken.xml', 'feed-ns0.xml', 'feed.xml']
>>> [os.path.realpath(f) for f in glob.glob('*.xml')] ②
['c:\\Users\\pilgrim\\diveintopython3\\examples\\feed-broken.xml',
'c:\\Users\\pilgrim\\diveintopython3\\examples\\feed-ns0.xml',
'c:\\Users\\pilgrim\\diveintopython3\\examples\\feed.xml']

这里返回当前目录下的所有.xml 文件。
列表解析接受.xml 文件列表并将其转化成全路径的列表
列表解析也可以过滤列表,生成比原列表短的结果列表。

>>> import os, glob
>>> [f for f in glob.glob('*.py') if os.stat(f).st_size > 6000] ①
['pluraltest6.py',
'romantest10.py',
'romantest6.py',
'romantest7.py',
'romantest8.py',
'romantest9.py']
你可以在列表解析的最后加入if子句来过滤列表。对于列表中每一个元素if 关键字后面的表达式都会被计算。
如果表达式的计算结果为True,那么这个元素将会被包含在输出中。
这个列表解析在当前目录查找所有.py 文件,而 if 表达式通过测试文件大小是否大于6000字节对列表进行过滤。
有6个符合条件的文件,所以这个列表解析返回包含六个文件名的列表

到目前为止的例子中的列表解析都只是用了一些简单的表达式, 乘以一个常数、调用一个函数或者是在过滤后返回原始元素。 

然而列表解析并不限制表达式的复杂程度。

>>> import os, glob
>>> [(os.stat(f).st_size, os.path.realpath(f)) for f in glob.glob('*.xml')] ①
[(3074, 'c:\\Users\\pilgrim\\diveintopython3\\examples\\feed-broken.xml'),
(3386, 'c:\\Users\\pilgrim\\diveintopython3\\examples\\feed-ns0.xml'),
(3070, 'c:\\Users\\pilgrim\\diveintopython3\\examples\\feed.xml')]
>>> import humansize
>>> [(humansize.approximate_size(os.stat(f).st_size), f) for f in glob.glob('*.xml')] ②
[('3.0 KiB', 'feed-broken.xml'),
('3.3 KiB', 'feed-ns0.xml'),
('3.0 KiB', 'feed.xml')]

这个列表解析找到当前工作目录下的所有.xml文件, 

        对于每一个文件构造一个包含文件大小(通过调用os.stat()获得)和绝对路径(通过调用os.path.realpath())的元组。
这个列表解析在前一个的基础上对每一个.xml文件的大小应用approximate_size()函数。


Dictionary解析

字典解析和列表解析类似,只不过它生成字典而不是列表。

>>> import os, glob
>>> metadata = [(f, os.stat(f)) for f in glob.glob('*test*.py')] ①
>>> metadata[0] ②
('alphameticstest.py', nt.stat_result(st_mode=33206, st_ino=0, st_dev=0,
st_nlink=0, st_uid=0, st_gid=0, st_size=2509, st_atime=1247520344,
st_mtime=1247520344, st_ctime=1247520344))
>>> metadata_dict = {f:os.stat(f) for f in glob.glob('*test*.py')} ③
>>> type(metadata_dict) ④
<class 'dict'>
>>> list(metadata_dict.keys()) ⑤
['romantest8.py', 'pluraltest1.py', 'pluraltest2.py', 'pluraltest5.py',
'pluraltest6.py', 'romantest7.py', 'romantest10.py', 'romantest4.py',
'romantest9.py', 'pluraltest3.py', 'romantest1.py', 'romantest2.py',
'romantest3.py', 'romantest5.py', 'romantest6.py', 'alphameticstest.py',
'pluraltest4.py']
>>> metadata_dict['alphameticstest.py'].st_size ⑥
2509
这不是字典解析; 而是列表解析。它找到所有名称中包含test.py文件,然后构造包含文件名和文件元信息(通过调用os.stat()函数得到)的元组。
结果列表的每一个元素是元组。
这是一个字典解析。 除了两点以外,它的语法同列表解析很类似。
首先,它被花括号而不是方括号包围;
第二,对于每一个元素它包含由冒号分隔的两个表达式,而不是列表解析的一个。
冒号前的表达式(在这个例子中是f)是字典的键;冒号后面的表达式(在这个例子中是os.stat(f))是值。
字典解析返回结果是字典。
这个字典的键很简单,就是glob.glob('*test*.py')调用返回的文件名。
每一个键对应的值是os.stat()函数的返回值。这意味着我们可以在字典中通过文件名查找到它的文件元信息。
元信息的一个部分是文件大小st_size。这个文件alphameticstest.py 的大小是2509字节。
同列表解析一样,你可以在字典解析中包含 if 字句来过滤输入序列,对于每一个元素字句中的表达式都会被求值。
>>> import os, glob, humansize
>>> metadata_dict = {f:os.stat(f) for f in glob.glob('*')} ①
>>> humansize_dict = {os.path.splitext(f)[0]:humansize.approximate_size(meta.st_size) \ 
...  for f, meta in metadata_dict.items() if meta.st_size > 6000} ②
>>> list(humansize_dict.keys()) ③
['romantest9', 'romantest8', 'romantest7', 'romantest6', 'romantest10', 'pluraltest6']
>>> humansize_dict['romantest9'] ④
'6.5 KiB'
这个字典解析获得当前目录下所有的文件的列表(glob.glob('*')),通过os.stat(f)获得每一个文件的元信息, 然后构造一个键是文件名,值是文件元信息的字典。
这个字典解析在前一个基础上过滤掉文件小于6000字节的文件(if meta.st_size > 6000), 并用过滤出的列表构造字典, 字典的键是文件名去掉扩展名的部分(os.path.splitext(f)[0]) ,字典的值是每个文件的人类可读的近似大小(humansize.approximate_size(meta.st_size))。
正如你在前一个例子中所看见的,有6个这样的文件,所以字典中有6个元素。
每一个键对应的值是approximate_size()函数返回的字符串。
这里是一个可能有用的通过字典解析实现的小技巧: 交换字典的键和值。
>>> a_dict = {'a': 1, 'b': 2, 'c': 3}
>>> {value:key for key, value in a_dict.items()}
{1: 'a', 2: 'b', 3: 'c'}

Set解析

集合也有自己的集合解析的语法。它和字典解析的非常相似,唯一的不同是集合只有值而没有键:值对。

>>> a_set = set(range(10))
>>> a_set
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> {x ** 2 for x in a_set} ①
{0, 1, 4, 81, 64, 9, 16, 49, 25, 36}
>>> {x for x in a_set if x % 2 == 0} ②
{0, 8, 2, 4, 6}
>>> {2**x for x in range(10)} ③
{32, 1, 2, 4, 8, 64, 128, 256, 16, 512}
集合解析可以接受一个集合作为参数。这个集合解析计算数字0-9这个集合的的平方。
同列表解析和字典解析一样, 集合解析也可以包含if 字句来在将元素放入结果集合前进行过滤。
集合解析的输入并不一定要是集合; 可以是任何序列。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值