测试字典键是否存在,不是None并且不为空。

18

我有一个可用的代码,但我想知道是否有更符合Python风格的方法。我有一个字典,我想要检查:

  • 键是否存在
  • 该值不是None(在这种情况下是SQL中的NULL)
  • 该值不仅仅是引号引号(空?)
  • 该值不仅仅包含空格

所以在我的代码中,“a”,“b”和“c”的键将成功,这是正确的。

import re

mydict = {
"a":"alpha",
"b":0,
"c":False,
"d":None,
"e":"",
"g":"   ",
}

#a,b,c should succeed
for k in mydict.keys():
    if k in mydict and mydict[k] is not None and not re.search("^\s*$", str(mydict[k])):
        print(k)
    else:
        print("I am incomplete and sad")

我上面的代码虽然有效,但看起来条件太多了。也许这确实是正确的解决方案,但我想知道是否有更符合Python风格的“存在且有内容”的方法或更好的方式来做到这一点?

更新 感谢大家提供精彩的答案和周到的评论。根据一些要点和建议,我稍微更新了问题,因为还有一些条件我没有考虑到,应该也要满足。我还将示例更改为循环(测试更容易一些吧?)。


那么 if mydict.get("a", "").strip(): 怎么样?None"" 都是假值。 - 0x5453
@0x5453 如果 mydict['a']None,那么这个方法会失败,因为 None 没有 strip 方法。 - chepner
@BradSolomon 只需要一个,不需要循环。 - sniperd
1
只是一个小提示 - 您可以直接执行 "a" in mydict 而不必调用 mydict.keys() - jwoos
1
请注意,这是由PEP-505覆盖的用例,尽管它目前被推迟,因此并不立即使用。 - chepner
显示剩余2条评论
7个回答

23
尝试获取值并将其存储在变量中,然后使用对象"真实性"来进一步处理该值。
v = mydict.get("a")
if v and v.strip():
  • 如果字典中没有键 "a"get 方法会返回 None,从而导致第一个条件失败。
  • 如果字典中有键 "a",但它的值为 None 或空字符串,则测试失败。如果它的值是一个空白字符串,strip() 方法会返回一个假值字符串,测试也会失败。

让我们来测试一下:

for k in "abcde":
    v = mydict.get(k)
    if v and v.strip():
        print(k,"I am here and have stuff")
    else:
        print(k,"I am incomplete and sad")

结果:

a I am here and have stuff
b I am incomplete and sad    # key isn't in dict
c I am incomplete and sad    # c is None
d I am incomplete and sad    # d is empty string
e I am incomplete and sad    # e is only blanks

如果你的值可能包含False0或其他“falsy”非字符串,那么你需要测试字符串,在这种情况下替换:

if v and v.strip():

by

if v is not None and (not isinstance(v,str) or v.strip()):

如果条件不是None,并且要么不是字符串(所有内容都匹配),要么是字符串但不为空,则条件匹配。


3

这里有一个简单的一行代码来检查:

  • 键存在
  • 键不为None
  • 键不为空字符串
bool(myDict.get("some_key"))

关于检查值是否只包含空格,需要更加小心,因为None没有strip()方法。

例如:

try:
    exists = bool(myDict.get('some_key').strip())
except AttributeError:
    exists = False

2

get 方法用于检查键是否存在,比遍历键更有效。它使用 O(1) 的复杂度而不是 O(n) 进行迭代以查看键是否存在。我的首选方法如下:

if mydict.get("a") is not None and str(mydict.get("a")).replace(" ", "") != '':
    # Do some work

2
你可以使用带有str.strip的列表推导式来处理字符串中的空格。
在Python中,使用if v是很自然的,以涵盖False-like对象,例如NoneFalse,0等。因此,请注意,仅当0不是可接受的值时,此方法才有效。
res = [k for k, v in mydict.items() if (v.strip() if isinstance(v, str) else v)]

['a']

0是个好选择。但我不能保证这个值不会为0。 - sniperd
你可以添加一个额外的子句:res = [k for k, v in mydict.items() if (v == 0) or (v.strip() if isinstance(v, str) else v)]。但现在你已经到了需要显式函数而不是一行代码的阶段。 - jpp

1

我有两个建议可以给你,尤其是如果你的主要问题是条件的长度。

第一个建议是检查键是否在字典中。你不需要使用"a" in mydict.keys(),你可以直接使用"a" in mydict

第二个建议是将条件拆分为存储为布尔值的较小条件,并在最终条件中检查这些条件:

import re

mydict = {
"a":"alpha",
"c":None,
"d":"",
"e":"   ",
}

inKeys = True if "a" in mydict else False
isNotNone = True if mydict["a"] is not None else False
isValidKey = True if not re.search("^\s*$", mydict["a"]) else False

if inKeys and isNotNone and isValidKey:
    print("I am here and have stuff")
else:
    print("I am incomplete and sad")

0

cond 是一个生成器函数,负责生成条件以短路方式应用于 all 函数。给定 d = cond()next(d) 将检查字典中是否存在 a,直到没有条件可应用为止,在这种情况下,all(d) 将计算为 True

mydict = {
  "a":"alpha",
  "c":None,
  "d":"",
  "e":"   ",
}

def cond ():
  yield 'a' in mydict
  yield mydict ['a']
  yield mydict ['a'].strip ()

if all (cond ()):
    print("I am here and have stuff")
else:
    print("I am incomplete and sad")

这个从函数式编程角度来看是可以工作的,但可能不太符合Pythonic,并且无法处理mydict ['a']为None的情况。 - avigil
@avigil 当然,它甚至无法处理'a' not in mydict的情况。 - marsouf

0

它确切地检查NoneType而不仅仅是None

from types import NoneType # dont forget to import this

mydict = {
"a":"alpha",
"b":0,
"c":False,
"d":None,
"e":"",
"g":"   ",
}

#a,b,c should succeed
for k in mydict:
    if type(mydict[k]) != NoneType:
        if type(mydict[k]) != str or type(mydict[k]) == str and mydict[k].strip():
            print(k)
        else:
            print("I am incomplete and sad")
    else:
        print("I am incomplete and sad")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接