在Python中跟踪数据类型
我希望这个问题是有效的……我最近(其实就是今天)决定学习一种脚本语言,所以我选择了Python。在浏览代码的时候,我感到有点不知所措,后来我意识到,原因是我不知道到底发生了什么数据类型转换之类的事情。
我的问题是:有没有什么约定可以帮助我跟踪数据类型是什么?我之前主要是用C语言,所以这让我感到有点困惑。有啥建议吗?
2 个回答
使用 isinstance(object, classinfo)
和 type(object)
。
在Python中,通常的做法是用一种叫做鸭子类型
的方法,意思是“如果它听起来像鸭子,走起来像鸭子,那它就足够像鸭子了”。
不过在一些特殊情况下,你确实需要检查某个东西的类型(为了对类似的类型做不同的处理……这通常不是个好主意),这时候就可以用到isinstance。
以前,isinstance
被认为是最后的手段,大家都警告不要过度使用它……虽然这种警告的核心思想依然有效,但自从Python 2.6以来,它有了一个重要的补充:检查某个东西是否是特定类的实例仍然不太好,但检查它是否是一个抽象基类(也就是ABC)则更常用,因为这样可以灵活地检查某个东西是否实现了某个接口。
举个例子,如果你想检查一个对象是否可以调用,以前你可能需要这样做:
if hasattr(type(obj), '__call__'): ...
而自从2.6版本后,推荐的做法变成了:
import collections
if isinstance(obj, collections.Callable): ...
这样做更直接、更简洁。更复杂的ABC,比如collections.MutableSequence
,意味着需要有很多不同的方法,这样的检查就更强大了。
检查某个具体类型的成员资格不太好,而检查ABC的成员资格更常用,这个道理在“Gang of 4”在他们的经典书籍《设计模式》的前半部分中表达得非常清楚(虽然主要是针对C++的,但其实适用范围更广!):编程要面向接口,而不是实现。
检查具体类的成员资格意味着你可能在编程时过于依赖实现;而用ABC检查时,实际上是在检查一个接口,这样很多问题就不再是大问题了(ABC不仅仅是接口——它们还可以为具体的子类提供“实现帮助”——但在讨论isinstance
时,把它们当作接口来理解可能是最有帮助的方式)。