Python 对象的可选链接:foo?.bar?.baz

在 JavaScript 中,如果我不确定链中的每个元素是否存在/不是未定义,我可以这样做foo?.bar,如果bar上不存在foo,解释器将默默地将其短路并且不会抛出错误。

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

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

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


慕森王
浏览 135回答 7
7回答

偶然的你

如果它是一本字典,你可以使用get(keyname, value){'foo': {'bar': 'baz'}}.get('foo', {}).get('bar')

有只小跳蛙

您可以使用getattr:getattr(getattr(foo, 'bar', None), 'baz', None)

白板的微信

最Pythonic的方式是:try:    # do something    ...except (NameError, AttributeError) as e:    # do something else    ...

慕田峪7331174

你可以使用格洛姆。from glom import glomtarget = {'a': {'b': {'c': 'd'}}}glom(target, 'a.b.c', default=None)  # returns 'd'https://github.com/mahmoud/glom

眼眸繁星

结合我在这里看到的一些东西。from functools import reducedef optional_chain(obj, keys):    try:        return reduce(getattr, keys.split('.'), obj)    except AttributeError:        return Noneoptional_chain(foo, 'bar.baz')或者扩展,getattr这样你也可以使用它作为替代品getattrfrom functools import reducedef rgetattr(obj, attr, *args):    def _getattr(obj, attr):        return getattr(obj, attr, *args)    return reduce(_getattr, attr.split('.'), obj)如果路径不存在,它仍然可以引发一个,并且您可以指定自己的默认值而不是“无” rgetattr。AttributeError

慕尼黑8549860

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

倚天杖

类可以覆盖__getattr__以返回缺失属性的默认值:class Example:&nbsp; &nbsp; def __getattr__(self, attr): # only called when missing&nbsp; &nbsp; &nbsp; &nbsp; return None测试它:>>> ex = Example()>>> ex.attr = 1>>> ex.attr1>>> ex.missing # evaluates to `None>>>但是,这不允许链接:>>> ex.missing.missingTraceback (most recent call last):&nbsp; File "<stdin>", line 1, in <module>AttributeError: 'NoneType' object has no attribute 'missing'它也不会处理调用不存在的方法的尝试:>>> ex.impossible()Traceback (most recent call last):&nbsp; File "<stdin>", line 1, in <module>TypeError: 'NoneType' object is not callable为了解决这个问题,我们可以创建一个代理对象:class GetAnything:&nbsp; &nbsp; def __getattr__(self, attr):&nbsp; &nbsp; &nbsp; &nbsp; return self&nbsp; &nbsp; def __call__(self, *args, **kwargs): # also allow calls to work&nbsp; &nbsp; &nbsp; &nbsp; return self&nbsp; &nbsp; def __repr__(self):&nbsp; &nbsp; &nbsp; &nbsp; return '<Missing value>'# Reassign the name to avoid making more instancesGetAnything = GetAnything()并返回它而不是None:class Example:&nbsp; &nbsp; def __getattr__(self, attr): # only called when missing&nbsp; &nbsp; &nbsp; &nbsp; return GetAnything现在它根据需要链接:>>> Example().missing_attribute.missing_method().whatever<Missing value>
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python