Python 使用高级方法解析文件,完成了底层解析语法后,就可以将原始数据重构为Python程序可用的形式。这类结构化方法适用于XML、JSON、CSV以及其他多种序列化数据的物理格式。
我们的目标是编写一组生成器函数,将数据解析为应用可用的形式。生成器函数对row_iter_kml()
函数搜索到的文本执行一些简单的转换,如下所示:
- 舍弃海拔高度属性,保留经度和纬度属性;
- 改变顺序,将
(longitude, latitude)
改为(latitude, longitude)
。
下面的辅助函数可以将这两次转换表示为一致的语法形式:
def pick_lat_lon(
lon: Text, lat: Text, alt: Text) -> Tuple[Text, Text]:
return lat, lon
这里创建了一个接收三个参数的函数,基于其中两个创建了二元组。其中的类型标示比函数本身还复杂。
如下所示使用该函数:
from typing import Text, List, Iterable
Rows = Iterable[List[Text]]
LL_Text = Tuple[Text, Text]
def lat_lon_kml(row_iter: Rows) -> Iterable[LL_Text]:
return (pick_lat_lon(*row) for row in row_iter)
该函数将pick_lat_lon()
函数应用于源数据的每一行,*row
参数负责将每个三元组转换为三个独立的值作为pick_lat_lon()
函数的参数,这个函数再从每个三元组中抽取数据并重新排序。
为了简化函数定义,我们创建了两个类型别名:Rows
和LL_Text
。类型别名既可以简化函数定义,又可以复用于其他函数,确保它们能处理相同类型的对象。
这种函数设计模式允许后续替换其中任何函数,以此简化代码重构。可以通过为不同的函数提供多种实现方法来达到这个目标。原则上,高质量的函数式语言编译器也会在优化过程中执行替换操作。
接下来组合上述函数,解析数据文件,构建可用的数据结构,如以下代码所示:
url = "file:./Winter%202012-2013.kml"
with urllib.request.urlopen(url) as source:
v1= tuple(lat_lon_kml(row_iter_kml(source)))
print(v1)
其中用urllib
命令打开的数据源是一个本地文件,也可以用它打开远端服务器上的KML文件。使用这种文件打开方式旨在确保不论数据源如何,都能以统一的方式打开。
这个脚本基于两个函数实现对KML文件的底层解析,row_iter_kml(source)
函数生成一个文本序列,lat_lon_kml()
函数抽取经度值和纬度值并重新排序。这样就为后续处理提供了中间结果,保证原始数据格式不影响后续处理流程。
运行上述代码,可得到如下结果:
(('37.54901619777347', '-76.33029518659048'),
('37.840832', '-76.27383399999999'),
('38.331501', '-76.459503'),
('38.330166', '-76.458504'),
('38.976334', '-76.47350299999999'))
这样就从复杂的XML文件中,采用基本纯函数的方式解析出了经度值和纬度值。由于生成结果是可迭代的,后续可使用函数式编程技术处理从文件中得到的每个点。
至此,就分别实现了底层的XML解析函数和上层的数据处理函数。解析XML后生成的是一组字符串元组,与CSV解析器生成的结果格式兼容,之后从SQL数据库中获取数据时,返回的结果也是类似的,这样就保证了上层处理函数能以相同的方法解析不同来源的数据。
下面将通过一系列方法把一组字符串转换为沿着一条路径的一系列数据点。该过程包含多次转换,既要重组数据,还要把字符串转换为浮点数。我们还会介绍简化和明晰后续处理步骤的方法,后续章节会继续使用这些数据,因为它们特别复杂。