如何在Python中以AND方式检查多个项是否为null

2 投票
3 回答
67 浏览
提问于 2025-04-14 16:47

我在想有没有一种简单的方法可以检查一个集合里的所有项目和依赖项是否都是空的。

假设我有一个变量 foo,它是一个字典,但可能是空的:

foo: Optional[dict] = None

我想检查 foo 本身是否不为空,或者它的某个键是否不为空:

if foo is not None and foo.get('bar') is not None:
   pass

使用“与”运算符时,它会在检查其他内容之前先判断第一个条件,所以我可以安全地检查一个可能为空的项目的其他键。

我在想有没有更简洁的方法来做到这一点,比如我们可以用 any()all() 函数。

我考虑过用列表推导式来实现,但这样会失败:


if not all(item is not None for item in [foo, foo.get('bar'), foo.get('baz')]:
   # Value Error! :sad

一种方法是使用 try/catch,但这样看起来不太好,也不够有趣……

我们不能用海象运算符,因为在列表推导式中它不能被赋值:


if not all (item for item in [foo := foo or {}, foo.get('bar'), foo.get('baz')]:
   # SyntaxError, can't use walrus in list comprehension

我也在想有没有一个维护得很好的工具可以实现这个目的。有没有更好的主意呢?

3 个回答

1

给定: "我想检查 foo 是否不为 None,或者它的某个键是否存在"

我假设你是想确认某个键的值不是 None,并且不需要短路求值。

我会先利用 or 来检查我们的字典,这样我们就可以调用 get() 方法。

可以这样写:

sum((foo or {}).get(key) is not None for key in test_keys)

或者也可以这样:

any(map(lambda key: (foo or {}).get(key) is not None, test_keys))

我觉得这两种写法都能返回你可以在 if 语句中使用的结果:

test_keys = ["bar", "bat"]

foo = None
if sum((foo or {}).get(key) is not None for key in test_keys):
    print(f"dictionary {foo} has a valid key")

foo = {"asf": True}
if sum((foo or {}).get(key) is not None for key in test_keys):
    print(f"dictionary {foo} has a valid key")

foo = {"bar": None}
if sum((foo or {}).get(key) is not None for key in test_keys):
    print(f"dictionary {foo} has a valid key")

foo = {"bar": 1}
if sum((foo or {}).get(key) is not None for key in test_keys):
    print(f"dictionary {foo} has a valid key")

应该会给你这样的结果:

dictionary {'bar': 1} has a valid key

请注意,我在这里也假设你想要一种简洁的写法,而不想用 if foo and ... 开头。如果你想这样做的话,可以参考@djaouadnm 的回答,那是我会采用的方法。

1

你可以使用模式匹配

foo = {"bar": 111}


# foo can be None and it will work:
match foo:
    case {"bar": int(val)}:
        print(val)

输出结果是:

111

或者:

foo = {"bar": 111}

match foo:
    case {"bar": val} if val is not None:
        print(val)

如果有多个值的话:

foo = {"bar": 111, "baz": "string"}

match foo:
    case {"bar": int(val1), "baz": str(val2)}:
        print(val1, val2)
3

简单来说,把 foo 和所有的 foo.get 分开,然后用一个 and 来连接它们:

if foo is not None and all(foo.get(key) is not None for key in ('bar', 'baz')):

你还可以用 key in foo 来检查这个键是否在字典里,这样做其实更安全。因为如果这个键存在,但在字典里的值是 None,那么用上面的方法就无法区分这两种情况:

if foo is not None and all(key in foo for key in ('bar', 'baz')):

撰写回答