Recipe 1.3. Testing Whether an Object Is String-like

Credit: Luther Blissett

测试对象是否类似于字符串

1. Problem

You need to test if an object, typically an argument to a function or method you're writing, is a string (or more precisely, whether the object is string-like).

检查一个对象(一般是函数或方法的参数)是否是字符串,或者说是否类似于字符串。

2. Solution

A simple and fast way to check whether something is a string or Unicode object is to use the built-ins isinstance and basestring, as follows:

检查其否是字符串或者unicode对象,可以使用内置函数 isinstancebasestring, 这是一种简单快捷的方法

   1 def isAString(anobj):
   2     return isinstance(anobj, basestring)

3. Discussion

The first approach to solving this recipe's problem that comes to many programmers' minds is type-testing:

很多程序员首先想到的解决方法是类型测试:

   1 def isExactlyAString(anobj):
   2     return type(anobj) is type('')

However, this approach is pretty bad, as it willfully destroys one of Python's greatest strengthssmooth, signature-based polymorphism. This kind of test would reject Unicode objects, instances of user-coded subclasses of str, and instances of any user-coded type that is meant to be "string-like".

但是,这种方法相当糟糕,因为它破坏了Python最强有力、基于信号的多态特性。这种测试排除了Unicode对象、用户自定义 str 子类的实例、以及其他类似于字符串的用户自定义类型实例。

Using the isinstance built-in function, as recommended in this recipe's Solution, is much better. The built-in type basestring exists exactly to enable this approach. basestring is a common base class for the str and unicode types, and any string-like type that user code might define should also subclass basestring, just to make sure that such isinstance testing works as intended. basestring is essentially an "empty" type, just like object, so no cost is involved in subclassing it.

使用内置函数 isinstance,是更好的解决方法。内置类型 basestring 的存在刚好是用于这种操作。basestring是 str 和 unicode 的通用基类,任何类似字符串的用户自定义也应该继承这个 basestring,这样可以确保 isinstance 测试成功。basestring本质上是“空”类型,就像对象一样,所以继承这个类型不会产生额外的耗费。

Unfortunately, the canonical isinstance checking fails to accept such clearly string-like objects as instances of the UserString class from Python Standard Library module UserString, since that class, alas, does not inherit from basestring. If you need to support such types, you can check directly whether an object behaves like a stringfor example:

但是,正规的 isinstance 测试在遇到 UserString实例时会失效,因为这个类并不是从 basestring 继承来的。如要支持这种类型的对象,你可以直接测试对象是否能像字符串一样操作,例如:

   1 def isStringLike(anobj):
   2     try: anobj + ''
   3     except: return False
   4     else: return True

This isStringLike function is slower and more complicated than the isAString function presented in the "Solution", but it does accept instances of UserString (and other string-like types) as well as instances of str and unicode.

这个函数有些慢,也比前面的 isAString函数复杂。但它可以测试 UserString 实例(以及其他类似字符串类型)和 str, unicode

The general Python approach to type-checking is known as duck typing: if it walks like a duck and quacks like a duck, it's duck-like enough for our purposes. The isStringLike function in this recipe goes only as far as the quacks-like part, but that may be enough. If and when you need to check for more string-like features of the object anobj, it's easy to test a few more properties by using a richer expression in the TRy clausefor example, changing the clause to:

一般的类型测试方法,可以看作 duck typing: 如果它走起来像个鸭子, 叫起来像个鸭子, 那么对于我们来说,就可以认为它是个鸭子了. isStringLike函数的功能只是完成了"叫得比较象"这一步,这还不够。如需要测试更多类似的类型,可以在 Try 中使用更多属性,比如:

   1 try: anobj.lower( ) + anobj + ''

}

In my experience, however, the simple test shown in the isStringLike function usually does what I need.

The most Pythonic approach to type validation (or any validation task, really) is just to try to perform whatever task you need to do, detecting and handling any errors or exceptions that might result if the situation is somehow invalidan approach known as "it's easier to ask forgiveness than permission" (EAFP). try/except is the key tool in enabling the EAFP style. Sometimes, as in this recipe, you may choose some simple task, such as concatenation to the empty string, as a stand-in for a much richer set of properties (such as, all the wealth of operations and methods that string objects make available).

try/except 是完成这种功能的重要手段,具体的try操作,需要根据你自己的需求来定。

4. See Also

Documentation for the built-ins isinstance and basestring in the Library Reference and Python in a Nutshell.


PyCookBook2