声明:由于Python Cookbook第二版使用的是Python 2.X的版本,所以有些例子和结论在Python 3.X上无法直接使用。而这个书的第三版又跟这本书不同,听别人说这版本很好,而我拿这本书来学习,所以书上很多结论我都是直接拿过来写下来,只是更新为3.X版本的。但自己才疏学浅,(不是自谦)可能很多地方写得不对。还望得到纠正。
问题
有时候需要测试一个对象,尤其是当你在写一个函数或者方法的时候,经常要测试传入的参数是否一个字符串(或者更准确地说,这个对象是否具有类似于字符串的行为模式)
解决方案
给出一个利用内置的 isinstance
和 str
来简单快速地检查某个对象是否是字符串的方法。(书中还有一个是Unicode对象,但Python 3已经是Unicode编码方式了)
def isAString(obj):
return isinstance(obj, str)
结果:
>>> isAString('Python')
True
>>> isAString('3.14')
True
>>> isAString(3.14)
False
>>> isAString('蟒蛇')
True
在书中, isinstance( obj, str )
中的str
是basestring
。但 basestring
在Python 3中已经用移除,用str
代替。无论是ASCII码还是Unicode码,或者是基于str
派生出来的任何类字符串的用户自定义类型都可以测试出。
但不幸的是,这个似乎完美的 isinstance
检查方案,对于 Python 标准库中的 collections
模块的提供的UserString
类的实例,完全无能为力。而 UserString
对象是非常明显的类字符串对象,只不过它不是从 str
派生出来的。用个例子:
>>> from collections import UserString
>>> like_string = UserString('abc')
>>> isAString(like_string)
False
如果要支持这种类型,可以直接检查一个对象的行为是否真的像字符串一样,比如:
def isStringLike(obj):
try:
obj + ''
except:
return False
else:
return True
这时候判断下,是可以返回True的:
>>> isStringLike(like_string)
True
这个 isStringLike()
函数比方案中给出的isinstance()
函数慢且复杂的多,但它的确使用于 UserString
(以及其他的类字符串类型)的实例,也使用于 str 和 Unicode。
从isStringLike
函数中,引出一个Python里很有意思和很重要的概念:鸭子类型,这个并不是Python独有的,Ruby也有的鸭子类型。鸭子类型是多态机制的知识范畴。
Python中通常的类型检查方法是所谓的鸭子判断法:如果它走路像鸭子,叫声也像鸭子,那么对于我们的应用而言,就可以认为他就是鸭子了。isStringLike
函数只不过检查了叫声部分,那其他的还不够。如果需要检查 obj
对象的更多的类字符串特征,可以改造 try 子句,让它检查更多细节,比如:
try:
obj.lower() + obj + ''
重点笔记:EAFP
进行类型验证(或者任何验证任务)的最具Python特色的方法是根据自己的预期去执行任务,在次过程中检测并处理由于不匹配产生的所有错误和异常。这是一个著名的处理方式,叫做“获得事后原谅总是比事先得到许可要容易的多”,简称EAFP。`try/except'是保证EAFP处理风格的关键工具。