Chinaunix首页 | 论坛 | 博客
  • 博客访问: 148441
  • 博文数量: 35
  • 博客积分: 2386
  • 博客等级: 大尉
  • 技术积分: 380
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-05 06:11
文章分类

全部博文(35)

文章存档

2011年(1)

2010年(2)

2009年(32)

分类: Python/Ruby

2009-10-09 20:24:31

摘自 Python Cookbook

Credit: Luther Blissett

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).

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:

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

Discussion

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

def isExactlyAString(anobj):
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".

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.

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:

def isStringLike(anobj):
try:
anobj + ''
except:
return False
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.

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:

    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).

阅读(1299) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~