简易数据结构访问实用程序

wildpath的Python项目详细描述


野生路径

访问复合(例如json)对象中的项的路径抽象 蟒蛇. < /P>

简介

本模块主要用作访问 复杂的数据结构。尤其是访问多个项目 需要for循环或其他构造,没有简单的 将嵌套位置作为单个参数传递的方法。这个模块解决了 通过介绍两个类来解决这个问题:

  • 路径 允许获取、设置和删除数据中的单个项 结构;针对速度进行了优化,
  • wildpath 也这样做,并允许通配符和布尔逻辑 (and,or,not)在获取、设置和删除多个项目的路径中 一个电话,
  • 两者都有迭代器(在公共基类中)来遍历所有 数据结构中的路径和值。

作为一个典型的例子,我们将调用 maps.googleapis.com 用于两个地址之间的路由。反应 如果格式良好,则超过390行json。但是我们只会 对各个台阶的地理位置感兴趣(依次 路线的说明。

在普通代码中,这看起来像(使用 json_route 调用google api的结果:

defget_geo_locations(json_route):geo_locs=[]forjson_stepinjson_route["routes"][0]["legs"][0]["steps"]:geo_locs.append({"start_location":json_step["start_location"],"end_location":json_step["end_location"]})returngeo_locsgeo_locations=get_geo_locations(json_route)

使用 wildpath 可以通过以下方法获得相同的结果:

location_path=WildPath("routes.0.legs.0.steps.*.*_location")geo_locations=location_path.get_in(json_route)

两者产生相同的项目列表:

[{"start_location":{"lat":52.0800134,"lng":4.3271703},"end_location":{"lat":52.0805958,"lng":4.3286669}},...# etc.]

实际上,函数定义被字符串替换,使用 wildpath.get_in 获取正确的查找逻辑。这有一些 优点:

  • 更少的代码行意味着更少的bug,
  • 更好的可读性和可维护性(一旦您习惯了 路径符号),
  • a 路径 野生路径 易于序列化 ( str(路径("a.b.c")) =="a.b.c" ),其中函数定义是 不是。

先决条件

可以使用 pip install wildpath 安装模块。它被测试了 对于Python2.7和Python3.3到3.6。

功能性

``path` 类支持,例如,path= path("a.0.b") obj={"a": [{"b": 1}}

  • 进入 :从数据结构获取项: 路径。进入(obj)
  • 在中设置:在数据结构中设置值: 路径设置(obj,值)
  • 删除 :从数据结构中删除项: 路径输入(obj)
  • 中有u:检查路径中是否存在值: 路径。已进入(obj)
  • 弹出:从数据结构中删除和返回项: 路径.弹出(obj)
  • 调用:调用数据中路径位置的方法 结构: 路径.调用(obj,*args,**kwargs)

它还有一些遍历 数据结构:

  • path.items(obj) :所有元组上的迭代器 对象,
  • path.paths(obj) :对象中所有路径上的迭代器,
  • path.values(obj) :对象中所有值的迭代器。

``wildpath` 类支持与 path 相同的功能, 添加以下内容:

  • 引用映射(例如 dict )或python类对象的键 可以包含通配符: wildpath("*.a*.b?") ,对于任何 字符串和 用于任何单个字符。通配符使用标准 python fnmatch.fnmatchcase
  • 引用序列的键(例如 list tuple )可以包含 切片: wildpath("1:3.::2") ,使用来自标准python的 。 切片表示法
  • 所有键都可以包含布尔逻辑,使用 &; for和, for或 对于不: 野生路径("a*&;!"*b" :以 'a'开头的键 而不是以 'b' 结尾。这也适用于切片键 野生路径("2:4 6:8") :索引2、3、6、7。

例如,wildpath.get_in返回简化的数据结构,跳过 非通配符/切片键,因此: python wildpath("a.*.x")。进入({"a": {"u": {"x":1}, "v":{"x": 2}}) ={"u":1,"v":2} 获取键"a"处的值,在键"u"和"v"上迭代,并获取 "x"键处的值。

请注意:

  • 类型的返回路径的迭代方法 野生路径 ,而不是路径
  • 如果在数据中找不到键、索引或属性,则 键错误 索引器错误 属性错误 reesp。将 升高,
  • get_in 可以采用默认的参数,如果没有则返回 值存在于路径位置: path.get_in(obj,none)
  • wildpath.get_in 可以采用 flat 参数,将 将生成的数据结构转换为平面列表: 路径。进入(obj,flat=true)
  • wildpath.get_in 将返回dict、list或normal的实例 值

示例

从某个工具中议程项目的示例结构开始:

agenda={"meeting":"progress on project X","date":"2017-8-14","start_time":"10:00","end_time":"11:00","invited":["Joe","Ann","Boo"],"items":[{"name":"opening","duration":"5 minutes","subjects":["purpose of the meeting"],},{"name":"progress","duration":"25 minutes","subjects":["milestones","project delays","actions"],},{"name":"closing","duration":"5 minutes","subjects":["questions","roundup"],},]}

路径

"path"类允许您在特定的 位置:

fromwildpath.pathsimportPathpath=Path("items.0.duration")assertstr(path)=="items.0.duration"# str(..) returns the original path stringduration=path.get_in(agenda)# retrieves value at path locationassertduration=="5 minutes"path.set_in(agenda,"10 minutes")# sets value at path locationassertpath.get_in(agenda)=="10 minutes"path.del_in(agenda)# deletes key-value at path loationassertpath.has_in(agenda)==False# has_in checks the presence of a value at the path location

wildpath

wildpath 支持与 path 相同的api,但另外还允许 在路径定义中使用通配符和切片来访问多个 结构中的项(存在 路径 类,因为 查找速度大大加快):

fromwildpath.pathsimportWildPathwildpath=WildPath("items.*.duration")# basic 'star' notationdurations=wildpath.get_in(agenda)# retrieves all the durations of the items on the agendaassertdurations==["5 minutes","25 minutes","5 minutes"]wildpath.set_in(agenda,["10 minutes","50 minutes","10 minutes"])# setting all the values,assertwildpath.get_in(agenda)==["10 minutes","50 minutes","10 minutes"]wildpath.set_in(agenda,"30 minutes")#  or replacing all with a single value,assertwildpath.get_in(agenda)==["30 minutes","30 minutes","30 minutes"]wildpath.del_in(agenda)# delete all the items at wildpath from the structureassertwildpath.has_in(agenda)==False# `has_in` checks if all the items at wildpath are there

获取会议的开始和结束时间:

wildpath=WildPath("*_time")assertwildpath.get_in(agenda)=={"start_time":"10:00","end_time":"11:00"}

类似地,它支持切片作为类似通配符的路径元素

wildpath=WildPath("items.0:2.name")assertwildpath.get_in(agenda)==["opening","progress"]wildpath=WildPath("items.!0:2.name")# slices can be negatedassertwildpath.get_in(agenda)==["closing"]wildpath=WildPath("items.-1::-1.name")# extended slicing also works, but orders are not reversed for a negative step parameterassertwildpath.get_in(agenda)==["opening","progress","closing"]

wildpath支持布尔逻辑:

# '|' is the OR operatorassertWildPath("start_time|end_time").get_in(agenda)=={"start_time":"10:00","end_time":"11:00"}# '&' is the AND operatorassertWildPath("start_*&*_time").get_in(agenda)=={"start_time":"10:00"}# '!' is the NOT operator:assertWildPath("!item?").get_in({"item1":"chair","item2":"table","count":2})=={"count":2}# parentheses can be used to indicate precedence:assertWildPath("!(a|b)")!=WildPath("!a|b")

注意事项

  • wildpath还支持嵌套对象列表中的属性查找 对象中的属性等,
  • wildpath.get_in的所有示例也适用于set_in, del_in pop_in has_in
  • 在wildpath.set_in(obj,value) 中,value可以是单个 值(将用于设置所有目标值)或数据 结构的"形状"与 野外路径。进入(obj)

迭代器

path类还定义了一些迭代器类方法:

defget_geo_locations(json_route):geo_locs=[]forjson_stepinjson_route["routes"][0]["legs"][0]["steps"]:geo_locs.append({"start_location":json_step["start_location"],"end_location":json_step["end_location"]})returngeo_locsgeo_locations=get_geo_locations(json_route)
0

打印

defget_geo_locations(json_route):geo_locs=[]forjson_stepinjson_route["routes"][0]["legs"][0]["steps"]:geo_locs.append({"start_location":json_step["start_location"],"end_location":json_step["end_location"]})returngeo_locsgeo_locations=get_geo_locations(json_route)
1

创建数据结构的替代表示:

defget_geo_locations(json_route):geo_locs=[]forjson_stepinjson_route["routes"][0]["legs"][0]["steps"]:geo_locs.append({"start_location":json_step["start_location"],"end_location":json_step["end_location"]})returngeo_locsgeo_locations=get_geo_locations(json_route)
2

path.items()有一个可选参数 all 如果设置为 true 将遍历所有路径、值组合,包括中介 路径:

defget_geo_locations(json_route):geo_locs=[]forjson_stepinjson_route["routes"][0]["legs"][0]["steps"]:geo_locs.append({"start_location":json_step["start_location"],"end_location":json_step["end_location"]})returngeo_locsgeo_locations=get_geo_locations(json_route)
3

将打印:

defget_geo_locations(json_route):geo_locs=[]forjson_stepinjson_route["routes"][0]["legs"][0]["steps"]:geo_locs.append({"start_location":json_step["start_location"],"end_location":json_step["end_location"]})returngeo_locsgeo_locations=get_geo_locations(json_route)
4

使用路径.items(obj,all=true) 和顺序 产生更多的操作,例如:

defget_geo_locations(json_route):geo_locs=[]forjson_stepinjson_route["routes"][0]["legs"][0]["steps"]:geo_locs.append({"start_location":json_step["start_location"],"end_location":json_step["end_location"]})returngeo_locsgeo_locations=get_geo_locations(json_route)
5

注意事项

  • 目前,这些迭代器无法处理循环关系。这个 将导致运行时错误(递归深度),
  • 迭代对象、可调用项和属性中的属性 以"\uu"开头的en不包括在内,
  • 迭代器返回生成器,而不是列表或dict。为此,请使用 列表(路径项(obj)) dict(路径i项目(obj))
  • 这些迭代器对于 数据结构:定义野生路径的起点,
  • 要使用字符串键将项目转换为dict dct={str(p):v表示p,v表示path.items(obj)}

路径操作

path wildpath 是元组的子类(通过basepath),因此 (几乎)所有元组方法都可以同时使用,例如:

defget_geo_locations(json_route):geo_locs=[]forjson_stepinjson_route["routes"][0]["legs"][0]["steps"]:geo_locs.append({"start_location":json_step["start_location"],"end_location":json_step["end_location"]})returngeo_locsgeo_locations=get_geo_locations(json_route)
6

注意,有些方法(如 \u add\uu path[1: )是 重写以返回正确的类(path或wildpath)

限制

由于用于分析路径的字符,在 目标数据结构将导致系统失败:

  • 对于 path wildpath :映射中的键(例如dict, orderedict)不能包含
  • 对于 wildpath :映射中的键不能包含字符 * &; 或更精确地说,如果它们是 现在,它们不能在野外路径中用于查找,
  • 注意 分隔符很容易在子类中替换, 允许像 "a/b/3/x" 而不是 "a.b.3.x" 这样的路径(以及 因此,路径 "a/b.c/3/x" 带有 b.c 字典键:
defget_geo_locations(json_route):geo_locs=[]forjson_stepinjson_route["routes"][0]["legs"][0]["steps"]:geo_locs.append({"start_location":json_step["start_location"],"end_location":json_step["end_location"]})returngeo_locsgeo_locations=get_geo_locations(json_route)
7

正在覆盖! &; 将需要更多的工作:覆盖 类属性 wildpath 中标记 并重写 keyparser.default_标记 。目前无法覆盖 代币 * 野生路径中

测试

unittests是标准的python unittests,因此可以运行。

作者

lars van gemerden(rational it)-初始代码和文档。

许可证

此项目可在license.txt中的mit许可下使用。

致谢

  • 非常感谢jasper hartong说服我开放源码 模块,
  • 感谢模块的创建者 布尔分析要容易得多。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
Java3D图表JavaGnuplotHybrid   java httpclient异常“org.apache.http.conn.ConnectionPoolTimeoutException:等待连接超时”   java如何使用Drive API连接到Google Drive文件夹   java如何正确组合@PathParams和@RequestBody?   使用JsonParser的java Jackson反序列化正在跳过@context的第一个键值对   java Twitter4j为getCreatedAt和getCountry获取空白或null   java doOnNext()不会被称为Spring Webflux   java Liberty批处理在使用与spring批处理相同的输入参数启动作业时未引发异常(JobInstanceAlreadyExistsException)   api使用WordNet有没有简单的基于Java的词义消歧?   Java和YAML:如何解析多个YAML文档并将它们合并到单个YAML表示?   swing Java:mouseClicked事件不总是触发   从firebase获取Json作为字符串在java中不起作用   java将带有extrastring的意图从活动发送到选项卡片段   Java中的调用方法问题   java是否可以在TestNG dataprovider类中注入变量   java如何在安卓 studio中使列表中的项目可单击并引导到具有特定格式的新页面   java程序在eclipse中运行,但不在终端中运行   java无法让mockito模拟公共类的公共方法