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 .