Python的isinstance函数

3
我不理解为什么isinstance函数的第二个参数需要一个元组而不是一些可迭代对象?
isinstance(some_object, (some_class1, some_class2))

运行正常,但是

isinstance(some_object, [some_class1, some_class2])

引发 TypeError 错误

2
这个问题可能会有所帮助。 - Lord Elrond
链接问题的答案为“为什么(_why._)”提供了一个良好的起点。在此发布答案前,每个人都应该先阅读它。 - alexis
谢谢你,Caleb!那帮助我理解了原因。 - Fanto
5个回答

3
据@Caleb在评论区中提供的关键链接,原因似乎是“只允许元组就足够了,这更简单,避免了某些边角情况的危险,而且对BDFL(即Guido)来说更整洁。”以下是一段摘自与Guido van Rossum的电子邮件对话的内容,其中明确解决isinstance函数的其他可迭代对象情况。请点击链接查看完整对话。

On Thu, Jan 2, 2014 at 1:37 PM, James Powell wrote:

This is driven by a real-world example wherein a large number of prefixes stored in a set, necessitating:

any('spam'.startswith(c) for c in prefixes)
# or
'spam'.startswith(tuple(prefixes))

Neither of these strikes me as bad. Also, depending on whether the set of prefixes itself changes dynamically, it may be best to lift the tuple() call out of the startswith() call.

...

However, .startswith doesn't seem to be the only example of this, and the other examples are free of the string/iterable ambiguity:

isinstance(x, {int, float})

But this is even less likely to have a dynamically generated argument.

And there could still be another ambiguity here: a metaclass could conceivably make its instances (i.e. classes) iterable.


@Fanto 如果这个答案对您有帮助,请点击投票按钮下方的复选标记接受它。 - Norrius
顺便说一下,感谢这个问题,我学到了str.startswith()可以将元组作为其参数! :-) 我从来没有想过要检查。 - alexis

1

根据文档,它的行为正是应该如此:https://docs.python.org/zh-cn/3/library/functions.html#isinstance

如果 classinfo 是类型对象的元组(或递归地,其他这样的元组),则返回 true 如果 object 是其中任何一个类型的实例。如果 classinfo 不是类型或类型元组和此类元组,则会引发 TypeError 异常。


1
这并没有真正回答“为什么”是这种情况。 - Norrius
1
请看@Caleb发布的链接:它是关于一个无关的问题,但解释了某些函数仅接受元组的原因。 - alexis

0

因为字符串也是“可迭代的一些内容”。所以你可以这样写:

isinstance(some_object, 'foobar')

它将检查some_object是否是fobar的实例。

显然这样不起作用,因此isinstance需要检查第二个参数是否不是字符串。由于isinstance需要进行类型检查,因此最好确保第二个参数始终是元组。


0

因为这就是语言设计的方式...

当你编写可以接受多种类型的代码时,使用固定类型进行直接测试比使用鸭子类型更容易。例如,由于字符串可迭代,当您想要接受字符串或字符串序列时,必须首先检查字符串类型。

在这里,我想不到限制为元组类型的强烈理由,但也没有将其扩展到任何序列的强烈理由。您可以尝试在python-ideas列表上提出建议。


1
请不要在python-ideas上提出这个建议!他们已经讨论过了,并且决定反对它。 - alexis

-1

在高层次上,需要一个容器类型进行 isinstance 检查,因此您有元组、列表、集合和字典作为内置容器。最有可能的是,他们选择元组而不是集合,因为对于 isinstance 的预期用例是少量类型,与集合相比,元组更快地检查包含关系。

可变性真的不是考虑因素。如果他们真的需要不可变性,在处理前他们可以将可迭代对象重新封装成元组即可。


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