如何检查 **kwargs 中是否存在某个关键字?

167

Python 3.2.3。这里有一些想法列出来了,它们适用于常规变量,但看起来 **kwargs 遵循不同的规则...那么为什么这不起作用,我该如何检查 **kwargs 中是否存在某个键?

if kwargs['errormessage']:
    print("It exists")

我也认为这应该可以工作,但实际上并没有 —

if errormessage in kwargs:
    print("yeah it's here")

我猜想是因为kwargs是可迭代的吗?我是否必须迭代它才能检查特定的键是否存在?


5
没有特别的规则,你只是忘记加引号了。 - Lennart Regebro
6个回答

257

你想要

if 'errormessage' in kwargs:
    print("found it")
获取errormessage的值。
if 'errormessage' in kwargs:
    print("errormessage equals " + kwargs.get("errormessage"))

这样,kwargs 就是另一个 dict。你的第一个例子,if kwargs['errormessage'],意思是“获取与 'errormessage' 键关联的值,然后检查其布尔值”。所以如果没有这样的键,你将得到一个 KeyError

你的第二个例子,if errormessage in kwargs:,意思是“如果 kwargs 包含由 "errormessage" 命名的元素”,除非 "errormessage" 是一个变量的名称,否则你将得到一个 NameError

我应该提到,字典还有一个方法 .get(),它接受一个默认参数(默认为 None),因此 kwargs.get("errormessage") 如果存在该键,则返回该值,否则返回 None(类似地,kwargs.get("errormessage", 17) 执行你期望的操作)。当你不关心键是否存在并且其值为 None 或键不存在时的区别时,这可能很方便。


3
谢谢您提供额外的解释! 对于刚接触Python的新手来说,获取一些背景信息和进一步的例子以了解可能性和不可能性总是有益的。在这个精神下:我认为,kwargs.get("errormessage", 17)如果errormessage不存在,则返回其值或者17 - 但我不确定。这是正确的吗? - Honeybear
啊,是的它确实可以。我在这里找到了答案。谢谢……我只是想确认一下。 - Honeybear

34

DSM 和 Tadeck 的回答直接解答了您的问题。

在我的脚本中,我经常使用方便的 dict.pop() 来处理可选和附加参数。以下是一个简单的 print() 包装器示例:

def my_print(*args, **kwargs):
    prefix = kwargs.pop('prefix', '')
    print(prefix, *args, **kwargs)

然后:

>>> my_print('eggs')
 eggs
>>> my_print('eggs', prefix='spam')
spam eggs

正如您所看到的,如果kwargs中不包含prefix,则默认情况下将空字符串''存储在本地prefix变量中。如果给定了prefix,则使用其值。

通常,这是编写任何类型函数包装器的紧凑且易读的方法:始终仅传递您不理解并且不知道是否存在的参数。如果您始终通过*args**kwargs进行传递,则会使代码变慢,并需要更多的打字,但如果被调用函数的接口(在本例中为print)发生更改,则无需更改代码。这种方法可以减少开发时间,同时支持所有接口更改。


1
感谢您展示如何为 prefix 分配默认值。 - HBat
我非常喜欢在包装函数时的传递行为——这使得这种技术在面对被包装函数的未来更新时特别健壮。 - mhand

15

就是这样:

if 'errormessage' in kwargs:
    print("yeah it's here")
你需要检查字典中是否有该键。语法是 some_key in some_dict (其中 some_key 是可哈希的东西,不一定是字符串)。
你链接的那些想法(这些想法)包含了检查特定键是否存在于由 locals()globals() 返回的字典中的示例。你的示例类似,因为你正在检查 kwargs 字典中特定键的存在性(该字典包含关键字参数)。

澄清一下:if some_key in kwargs: 不更像是 if some_key in some_dict.keys(): 吗?换句话说,kwargs 不更像是一个解包后的字典吗? - PatrickT
哦,等等!你有一个相关的答案,它相当明确地解释了事情:https://dev59.com/-mkv5IYBdhLWcg3wlRz1 - PatrickT

6

一种方法是自己添加!如何做到呢?通过将kwargs与一些默认值合并。这种方法并不适用于所有情况,例如,如果键提前不为您所知,则不适用。但是,如果它们是已知的,这里有一个简单的例子:

import sys

def myfunc(**kwargs):
    args = {'country':'England','town':'London',
            'currency':'Pound', 'language':'English'}

    diff = set(kwargs.keys()) - set(args.keys())
    if diff:
        print("Invalid args:",tuple(diff),file=sys.stderr)
        return

    args.update(kwargs)            
    print(args)

默认值设置在字典args中,该字典包含我们所期望的所有键。首先检查kwargs中是否有任何意外的键。然后,我们使用kwargs更新args,这将覆盖用户设置的任何新值。我们不需要测试键是否存在,现在将args用作参数字典,并不再需要kwargs

2

您可以轻松自行发现这些内容:

def hello(*args, **kwargs):
    print kwargs
    print type(kwargs)
    print dir(kwargs)

hello(what="world")

23
去掉“easy”,这就是更好的答案。如果对每个人来说都很容易,那么我们就不需要这个网站了。如果你从未编程或者是 Python 初学者,寻找in运算符本身并不容易。它只在dict.get()dict.setdefault()帮助文件中被提示。 - cfi

1
if kwarg.__len__() != 0:
    print(kwarg)

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