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 .