1 引言

各位朋友大家好,欢迎来到月来客栈,我是掌柜空字符。

不知道各位客官在行走江湖的过程中有没有遇到类似这样的情景:

场景一:

假如现在有一个元素全为自然数的列表,需要你将其按奇数和偶数的方式把这些自然数分成两类,并存放到一个字典中。对于这个场景,掌柜相信每个客官看完之后就能写出类似如下的代码:

在上述代码中,我们首先定义了一个包含有两个key的字典;然后依次遍历列表中的每一个数并按条件放到字典中的不同地方。

再例如现在有一个元素全为自然数的列表,需要你将其中相同的元素放到同一个列表中。对于这种类似场景,最直接的写法就是:

可以看到,虽然在上述两个场景中我们都能够以最直接的方式给实现出来,但总觉得繁杂了一点。那有没有更简单的方式呢?

场景二:

在数据预处理的过程中(又尤其是NLP)通常都会返回包含一串元素的数据类型。类似某数据预处理后返回的类型为一个二维列表,列表中的每一个元素对应的都是一个样本(列表),每个样本里面又包含了该样本对应的信息。例如SQuAD数据预处理后每个样本就会返回类似如下的字段:

对于这样的形式,通常在后续都会以元素索引的方式来取每个样本中的对应内容。但是这样做面临的一个问题就是,当整个数据样本作为参数传到不同(多个)函数之后,我们往往就会忘了每个索引所指代的元素到底是什么含义,又需要跳转到最开始的地方数一数来确定。而这为我们写代码带来了极大的不便。那有没有什么好的方法能够解决这个问题呢?

2 解决方案

2.1 默认字典defaultdict

对于场景一当中的问题,我们可以通过collections包中的defaultdict模块来实现。从模块的名字可以看出,它返回的仍旧是一个字典,只是我们在定义这个字典的时候可以指定它的默认类型。例如可以通过defaultdict(list)来得到一个默认元素为list的字典。

有了defaultdict后,场景一中的第二个示例我们便可以通过如下代码来实现:

从上面的输出结果可以看出,defaultdict返回字典和普通的dict字典在通过Key取Value的用法都一样。同时也可以通过同dict一样的方式来遍历defaultdict字典:

当然,对于defaultdict来说,其默认指定的类型还可以是strdict等任何你所需要的类型。

2.2 命名体元组namedtuple

对于场景二中的问题,我们可以借助collections包中的namedtuple模块来完成。从名字来看namedtuple返回的本质上是一个元组,只是元组里面的元素可以通过其对应的名称以类成员变量的方式来进行访问与使用。

因此,对于类似场景二中的问题,我们便可以通过如下所示代码来进行解决:

在上述代码中,第5行用来定义一个包含有两个元素的元组,且该元组的名称为point,两个元素对应的名称分别为xy;第9-10行则是分别将这5个点依次保存到列表points中,可以看到此时points中的每一个元素都是一个命名体元组了;第13-14行则是遍历列表中的每一个元素,然后通过以元组中元素名称的方式来访问对应的值。

所以,在有了命名体元组这一利器之后,对于场景二中的问题便可以通过定义一个相应的namedtuple来进行解决。

本次内容就到此结束,感谢您的阅读!如果你觉得上述内容对你有所帮助,欢迎点赞转发分享三连!若有任何疑问与建议,请添加掌柜微信nulls8进行交流。青山不改,绿水长流,我们月来客栈见