Python Cookbook 第二版 汉化版 [Recipe 1.3] 测试一个对象是否为 String-like 对象

Recipe 1.3. Testing Whether an Object Is String-like
Recipe 1.3. 测试一个对象是否为 String-like 对象

Credit: Luther Blissett


问题

您需要一个对象(通常会作为实参用于您正在撰写的方法或函数)进行检测,查看其是否为字符串(更准确地说,是否为 string-like 对象)。


解法

要检查某对象是否为字符串或 Unicode 对象,简单快速的办法是使用内建的 isinstancebasestring ,用法如下所示:

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


讨论

针对本问题,许多程序员脑海中浮现出来的做法是类型检测:

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

然而这种做法相当糟糕,因为它经意地破坏了 Python 最强大的能力之一,即平滑的、基于签名式(signature)的多态机制。该解法中的测试无法处理 Unicode 对象、用户编写的 str 子类的实体,以及用户编写的任何 string-like 类型的实体。

本条目所推荐的“使用 isinstance 内建函数”的方案要好得多。内建类型 basestring 正是为支持此方案而存在的。basestringstr unicode 类型的公共基类,用户代码中定义的任何 string-like 类型都应该以 basestring 作为基类,以保证上述 isinstance 检测能够正常发挥效用。与 object 一样,basestring 基本上是个“空”类型,因此继承该类并无额外开销。

不幸的是,诸如 Python 标准库 UserString 模块中 UserString 这样的类,明显是 string-like ,但却无法被正儿八经的 isinstance 检测所接受,因为……唉……UserString 类没有继承自 basestring 。若您需要检测这样的类型是否为 string-like ,您可以直接检查该类型对象的行为是否像一个字符串,例如:

def isStringLike(anobj):
    try: anobj + ''
    except: return False
    else: return True

isStringLike 函数比本条目解法中展示的 isAString 函数慢一些,也更为复杂,但其确是既可以接受 UserString(以及其他 string-like 类型)的实体,也可以接受 str unicode 实体。

Python 中进行类型检查(type-checking)的通用方案称为“duck typing”:若该类型的对象“走”起路来像鸭子,“叫”起来也像鸭子,于我们而言它就很像鸭子了。本条目中的 isStringLike 函数只能算是“叫”起来像鸭子,但可能足够用了。若您需要检查对象里更多的 string-like 机能,可以通过 try 语句来完成,在 try 区块中加入丰富的表达式来检查更多的对象属性,例如:

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

译注:duck typing 是 Python、Ruby 等动态语言中常见的一种编程思想,其基本思想是:若某对象走起路来像鸭子,叫起来也像鸭子,那就当它是鸭子。考察对象类型时,不关心所面对的对象实际是什么类型,只关心该对象能否完成我们期望其完成的任务;进行类型检查时,不采用常规的、专门用于检测类型的函数或方法(比如 isinstance() type()),而是通过检查对象所包含的方法或属性,来确定该对象能否完成期望的任务。换句话说,duck typing 强调的是类型的接口,而不是类型的内部详情。贯彻此思想而编写出来的设计良好的代码,往往由于能够支持“以多态方式来替换类型”,从而增强了代码的可伸缩性。Dave Thomas 所著的 Programming Ruby: The Pragmatic Programmers' Guide, Second Edition 中的第 23 章专门讨论了 duck typing ,可供参考。

然而以笔者的经验来看,isStringLike 函数中的简单测试通常能够满足笔者的需求。

对于类型验证这样的任务(甚至是任何其他验证任务),最具 Pythonic 风味的做法就是直接尝试完成任务,在遇到非法情形时,测出并处理任何可能导致的错误或异常——这种做法被称为“it's Easier to Ask Forgiveness than Permission(EAFP)”,意即“寻求体谅比寻求应允更容易。”实现 EAFP 风格的关键设施是 try/except 机制。有时候(比如本条目的情形),您可能会选择一些简单任务(比如与空字符串进行连接)来作为对象中丰富的属性集合(比如字符串对象所支持的丰富的操作和方法)的代言者,参与类型检查。


请参见

Library ReferencePython in a Nutshell 一书中关于内建的 isinstancebasestring 的文档。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值