阅读:十二月 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
函数更加方便的封装错误信息。