转载

在 Python 里小试 Optional 手法

Python 天生不支持 Option 类型, typing 有个 Optional , 但也就只能用来当 type hints 而已。

当然,这并不妨碍我们自行贯彻 Optional 手法。今天我写的函数 parse 会把所有 *_pathname 都打开并解析其内容,它有四个可选参数,其中三个的默认值是 None .

def parse(
log_pathname,
label_pathname,
tp_pathname=None,
fp_pathname=None,
fn_pathname=None,
overlap_rate=kitti_rate):

也就是说用户可以直接调用 parse(log_pathname, label_pathname) , 即不打算提供剩下的参数。这时 parse 可以自发构造临时文件并代替所要打开的文件,前者当然是空的,于是不怕照常被解析。

于是我们就 需要判断对象是否为 None , 是则继续沿用原来的值,反之则用指定默认值 的函数了,即类似于:

def a(b, c):
if b is None:
return c
else:
return b
d = None
a(d, 1)
e = 2
a(e, 1)

显然 a(d, 1) 为 1, a(e, 1) 为 2.

我看了支持 Optional 的编程语言,Haskell 用 fromMaybe (大概?),Rust 用 unwrap_or , C++17 用 std::optional::value_or (顺便独家爆料下,起这函数名的同行就在C++ 众里,真是吾辈的福气)。

虽说 Python 没有这样的函数,但 已经有足够简单好用的表达式了 : a = b or c .

言归正传,光判断 *_pathname 还不够,得用 tempfile.NameTemprorayFile 充当前者为 None 时所打开的文件才行。于是我仿照 Rust 的 unwrap_or , 封装了一个特化函数:

def _unwrap_or_tempfile(pathname, mode='r'):
if pathname is None:
return tempfile.NamedTemporaryFile(mode=mode, delete=False)
else:
return pathname.open(mode)

最后,其实 Python 标准库也有若干当对象为 None 时就返回指定 default 值的函数: next(iterable[, default]) , dict.get(key[, default])dict.setdefault(key[, default]) 等等。 于是我们可以在需要时,贯彻这样的 Optional 手法。

Written with StackEdit .

原文  http://tech.acgtyrant.com/在-Python-里小试-Optional-手法/
正文到此结束
Loading...