有时候需要测试一个对象,尤其是你写一个函数和方法,经常要测试传入的参数是否是一个字符串,如果采用了其他语言的类似的处理方式,测试传入参数的类型type(),通常就是这么写:
>>> def isString(obj):
return type(obj) is type('')
>>> isString('Hello')
True
>>> isString([1, 2, 3, 4])
False
上面的处理方式至少有三个错误:
1) Unicode对象无法通过测试
>>> def isString(obj):
... return type(obj) is type('')
...
>>> isString(u'aaa')
False
2) 用户自己编写的str子类通不过测试
>>> class ClassTest(object):
def __str__(self):
return "THIS IS CLASS TEST!"
>>> def isString(obj):
return type(obj) is type('')
>>> ct = ClassTest()
>>> str(ct)
'THIS IS CLASS TEST!'
>>> isString(ct)
False
3) 最重要的是破坏了Python最重要,强大的特性的:多态机制!
>>> '4' *4
'4444'
>>> 4 * 4
16
>>>
多态机制的机制,是Python的一个非常非常重要的特性,比如像上面的如果是字符串'4'*4,则Python识别这个是字符串的对象,字符串对象*4,则是4个'4',如果是整数4,则4 * 4,得出的结果则是16,像上面的例子其实有很多,这是Python强大的源泉,如果使用type()进行判断,则无形中破坏了Python最为强大,最为平滑,最为灵活的多态进制!!!
所以基于上面的的缺陷,理想的方式是,即可检查字符串和自己定义的str,又可以检查Unicode对象,还不会破坏Python的多态机制,可以这么写:
>>> def isString(obj):
... try:
... obj + ''
... except:
... return False
... else:
... return True
...
>>> isString(u"Hello,World!")
True
上面的方法就是著名的"鸭子判断法",如果是鸭子,那么它就一定具备鸭子的特征!比如说字符串,它必定可以使用一个字符串和空字符串来做合并操作,也有lower(),title()等方法。
>>> "ABCD" + " "
'ABCD '
>>> "ABCD".lower()
'abcd'
>>> 'hello'.title()
'Hello'
所以完美的写法就是多检查一些其他细节,特征! 比如鸭子,判断它走路是否像鸭子,叫声是否像鸭子!
>>> def isString(obj):
... try:
... obj.lower() + obj.title() + obj + ""
... except:
... return False
... else:
... return True
...
>>> isString("Hello ")
True
>>> isString(u"Hello")
True