beta

阅读:十二月 26 日

Fastest way to uniquify a list in Python ≥3.6

(来自 ImportPython #156

https://www.peterbe.com/plog/fastest-way-to-uniquify-a-list-in-python-3.6

如何去除 Python 列表中重复的元素?作者在 11 年前写过一篇博客比较了各种方法的性能,现在又为 Python 3.6 做了更新。

在具体看各种实现方法之前,先自己动脑想了一下:

如果只是去重,而不考虑列表元素的原顺序,那么只需要构造一个集合再转回列表,list(set(input)) 就能解决。

如果需要保持原顺序,并没有什么特别简单的方法。用一个集合存储列表中的元素,遍历列表,对于每一个元素,如果不存在于集合中,则放入输出列表,然后加入集合。用产生式应该可以做到:

结果是,在不考虑顺序的情况下,list(set(input)) 打败了各种 O(n) 方法。而在需要考虑顺序的情况下,Python 3.6 新引入了 dict 保持元素添加顺序的特性,因此可以用 list(dict.fromKeys(input)) 来实现,而且性能最佳。


Stop using .IO Domain Names for Production Traffic

https://hackernoon.com/stop-using-io-domain-names-for-production-traffic-b6aa17eeac20

Stream 的作者写的文章。之前他们有一部分用户无法解析 getstream.io 这个域名,调查之后发现是 .io 的 6 台根服务器里有两台出错了。更严重的是,负责 .io TLD 的 NIC.io 处理问题的速度和态度都令人难以接受。作者认为 .io 域名虽然很酷,但并不适合用于对可用性有要求的服务。相比之下,.com/.org/.net 这些常规 TLD 虽然看起来没有那么酷,但稳定才是一个域名服务的关键。


Error handling patterns in Go

https://mijailovic.net/2017/05/09/error-handling-patterns-in-go/

Go 从某种程度上可以看作 C 的升级版,因此在错误处理的方式上也与 C 非常相似。不同的是,C 常常使用整数等原始类型表示错误码并作为函数的返回值,真正的执行结果就需要通过指针参数来传递;而 Go 支持多返回值,因此可以将函数的执行结果与错误一同返回,同时也有了专门的错误类型。

作者提出了在处理 Go 代码错误时的三条 pattern:

永远都要处理错误。忽略函数错误的习惯很可能导致一些隐蔽错误的产生,因此每一条可能产生错误的函数调用都要对错误进行判断和处理。如果通过 defer 执行的函数产生了错误,可以通过一个匿名函数封装来简单处理,但是会产生很多胶水代码。用一个专门的函数来做 defer 中的工作,可以有效地提升代码的表达能力。例如,对比以下两段代码:

第二段代码在程序的主要逻辑上显然更清晰。

不要滥用 err != nil。如果连续多次执行一个可能产生错误的函数,那么为每一个函数都判断 err != nil 显然是一种很蠢的做法。作者建议对函数进行封装,通过一个 struct 来封装函数所有者的实例和错误,并重新实现对应的函数,只在没有发生过错误的情况下执行目标函数。这样,多次执行函数时如果发生错误,那么只会停留在初次发生错误的场景。

为错误添加上下文。将底层实现的细节错误直接 return err 抛给外层的高级逻辑处理,显然不是一种很好的做法。可以用 fmt.Errorf 函数为错误添加相关信息,或者可以用 errors 这个库的 Wrap 函数更加方便的封装错误信息。