假设我有一个变量x
,它是一个未知的数据类型。我也有一些随机函数foo
。现在我想按照以下几点做点什么:
如果x
是可以使用**解压缩的类型,例如字典,请致电foo(**x)
。否则,如果x
是可以使用*解压缩的类型,例如元组,则调用foo(*x)
。否则,只需致电foo(x)
。
是否有一种简单的方法可以检查是否可以通过**或*解压缩类型?
我目前正在做的是检查x的类型并执行如下操作:
if type(x) == 'dict':
foo(**x)
elif type(x) in ['tuple','list', ...]:
foo(*x)
else:
foo(x)
但问题是我不知道实际上可以解压缩的完整数据类型列表,而且我也不确定用户定义的数据类型是否可以有一个允许它们解压缩的方法
答案 0 :(得分:2)
您可以使用try:
foo(**x)
except:
try:
foo(*x)
except:
foo(x)
:
{{1}}
它的粗糙,并没有区分为什么发生异常(可以通过检查异常的类型来缓解),但是不需要尝试和枚举哪些类型可以被称为哪种方式。
答案 1 :(得分:1)
让我们检查错误时收到的错误:
>>> x = 1
>>> f(*x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() argument after * must be a sequence, not int
>>> f(**x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() argument after ** must be a mapping, not int
很好:所以我们需要*
的序列类型和**
的mappping类型。其余的相当简单:Python 3 docs状态:
有三种基本序列类型:列表,元组和范围对象。专门用于处理二进制数据和文本字符串的其他序列类型将在专门的章节中介绍。
检查var是否为序列类型的故障安全方法是:
>>> import collections
>>> all(isinstance(x, collections.Sequence) for x in [[], (), 'foo', b'bar', range(3)])
True
(有关详细信息,请参阅Python: check if an object is a sequence)
根据docs,映射类型为dict
:
目前只有一种标准的映射类型,即字典。
您可以使用isinstance
以相同的方式检查,这甚至会处理派生类:
>>> from collections import OrderedDict
>>> from collections import Counter
>>> all(isinstance(x, dict) for x in [{}, OrderedDict(), Counter()])
True
所以你可以这样做:
import collections
if isinstance(x, dict):
foo(**x)
elif isinstance(x, collections.Sequence):
foo(*x)
else:
foo(x)