繁体   English   中英

Python中的可选链接

[英]Optional chaining in Python

在 JavaScript 中,如果我不确定链的每个元素是否存在/是否未定义,我可以执行foo?.bar ,如果foo bar解释器会默默地短路它而不抛出错误.

Python中有类似的东西吗? 现在,我一直在这样做:

if foo and foo.bar and foo.bar.baz:
    # do something

我的直觉告诉我,这不是检查链中每个元素是否存在的最佳方法。 有没有更优雅/Pythonic 的方式来做到这一点?

大多数pythonic方式是:

try:
    # do something
    ...
except (NameError, AttributeError) as e:
    # do something else
    ...

您可以使用getattr

getattr(getattr(foo, 'bar', None), 'baz', None)

如果它是一个字典,你可以使用get(keyname, value)

{'foo': {'bar': 'baz'}}.get('foo', {}).get('bar')

您可以使用格洛姆。

from glom import glom

target = {'a': {'b': {'c': 'd'}}}
glom(target, 'a.b.c', default=None)  # returns 'd'

https://github.com/mahmoud/glom

结合我在这里看到的一些东西。

from functools import reduce


def optional_chain(obj, keys):
    try:
        reduce(getattr, keys.split('.'), root)
    except AttributeError:
        return None

optional_chain(foo, 'bar.baz')

或者改为扩展getattr ,以便您也可以将其用作getattr的替代品

from functools import reduce


def rgetattr(obj, attr, *args):
    def _getattr(obj, attr):
        return getattr(obj, attr, *args)
    return reduce(_getattr, attr.split('.'), obj)

使用rgetattr如果路径不存在,它仍然可以引发AttributeError ,并且您可以指定自己的默认值而不是 None。

将其他一些答案组合到一个函数中,可以为我们提供易于阅读的内容以及可以与对象和字典一起使用的内容。

def optional_chain(root, *keys):
    result = root
    for k in keys:
        if isinstance(result, dict):
            result = result.get(k, None)
        else:
            result = getattr(result, k, None)
        if result is None:
            break
    return result

使用此函数,您只需在第一个参数之后添加键/属性。

obj = {'a': {'b': {'c': {'d': 1}}}}
print(optional_chain(obj, 'a', 'b'), optional_chain(obj, 'a', 'z'))

给我们:

{'c': {'d': 1}} None

我喜欢像 Kotlin 这样的现代语言,它允许这样做:

foo?.bar?.baz

最近我尝试在 python 中实现类似的东西很有趣: https ://gist.github.com/karbachinsky/cc5164b77b09170edce7e67e57f1636c

不幸的是,问号在 python 中的属性名称中不是有效符号,因此我使用了 Unicode 中的类似标记:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM