我的问题是:我想要可靠地捕获由多个解压缩字典的命名空间冲突引起的错误。什么是规范方式?搜索并没有真正揭示这个问题的任何帮助。
假设我有两个类似字典的变量,我想将字符串键混合在一起。它们表示类似名称空间的对象,因此我想确保它们没有任何名称冲突。我可以这样做,冲突给我一个TypeError
:
>>> d1 = dict(a=1)
>>> d2 = dict(a=2)
>>> format_args = dict(**d1, **d2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type object got multiple values for keyword argument 'a'
优异。因此,当从两个关键字类型参数构造命名空间时,我可以(天真地)做这样的事情:
# test.py
from collections import OrderedDict as od
def kwargs_mash(kwargs1, kwargs2):
try:
# use unpacking to disallow multiple argslists to same member name
args = od(**kwargs1, **kwargs2)
except TypeError:
key_conflict = next(k for k in kwargs1 if k in kwargs2)
# more descriptive error message
raise TypeError('Multiple argument sets provided under member name: {}.'.format(key_conflict)) from None
但是,尝试解包非映射类型的对象也会产生TypeError
:
>>> x=1
>>> d=dict(**x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type object argument after ** must be a mapping, not int
这是一个问题,因为传递给kwargs_mash
的参数可能不是Mapping
个对象,而我改进的,更具描述性的TypeError
消息将不再是一个很好的描述发生了什么。
我的解决方案如下,并且有效。
def kwargs_mash(kwargs1, kwargs2):
try:
# use unpacking to disallow multiple argslists to same member name
args = od(**kwargs1, **kwargs2)
except TypeError as exc:
if 'multiple values for keyword argument' in str(exc):
key_conflict = next(k for k in kwargs1 if k in kwargs2)
# more descriptive error message
raise TypeError('Multiple argument sets provided under member name: {}.'.format(key_conflict)) from None
else:
raise
然而,this answer to another question称这种做法“脆弱”,我倾向于同意。
这是Python。必须有更好的方法。
也许最好的办法就是:
def kwargs_mash(kwargs1, kwargs2):
# ensure compatible arguments
kwargs1, kwargs2 = od(**kwargs1), od(**kwargs2)
# continue as before...