如何找出Python对象是否是字符串?


402

如何检查Python对象是字符串(常规还是Unicode)?


18
杰森指的是鸭子打字(如果它像鸭子一样嘎嘎叫,那可能就是鸭子)。在Python中,您经常在任何类似字符串的对象上“让代码工作”,而无需测试它是字符串还是字符串子类。有关更多信息,请参见:docs.python.org/glossary.html#term-duck-typing
Ben Hoyt,2009年

4
那就是我所喜欢的。我通常会问一个问题,没有得到回答,人们告诉我我无论如何都不应该这样做,为什么这样做,所以我成长为一名程序员。=)
physicsmichael

24
+1:仅仅因为很少需要答案,并不意味着问题是无效的。虽然,我认为在此谨慎行事很好,但我认为降低这个问题不值得。
Trevor

17
这可能是Python中类型检查的最合法用法。字符串是可迭代的,因此以任何其他方式将它们与列表区分开是一个坏主意。
ojrac 2013年

3
在某些情况下,肯定有必要将字符串与其他可迭代对象区分开。例如,请参阅pprint模块中的PrettyPrinter的源代码。
saxman01 2014年

Answers:



178

Python 2

要检查对象o是否是字符串类型的子类的字符串类型:

isinstance(o, basestring)

因为str和和unicode都是的子类basestring

检查的类型o是否完全是str

type(o) is str

检查是否o是的实例str或的任何子类str

isinstance(o, str)

以上还为Unicode字符串的工作,如果你更换str使用unicode

但是,您可能根本不需要进行显式类型检查。“鸭子打字”可能符合您的需求。请参阅http://docs.python.org/glossary.html#term-duck-typing

另请参阅在python中检查类型的规范方法是什么?


赋值之前引用的局部变量“ str”
约翰·克特吉克

@johnktejik python3与python2 您需要检查basestringpy2。
erikbwork

170

Python 3

在Python 3.x basestring中,str唯一的字符串类型(具有Python 2.x的语义unicode)不再可用。

因此,Python 3.x中的检查只是:

isinstance(obj_to_test, str)

这是对官方转换工具的修复2to3:转换basestringstr


94

Python 2和3

(兼容)

如果您不想检查Python版本(2.x与3.x),请使用sixPyPI)及其string_types属性:

import six

if isinstance(obj, six.string_types):
    print('obj is a string!')

six(一个重量很轻的单文件模块)中,它只是在做这件事

import sys
PY3 = sys.version_info[0] == 3

if PY3:
    string_types = str
else:
    string_types = basestring

另外,您也可以使用futurePyPI)保留名称:from past.builtins import basestring
David Nemeskey

1
顺便说一句,备忘单是Python版本兼容性的绝佳资源。
David Nemeskey '17

1
不使用任何导入怎么办?首先尝试basestring,然后退回到str。例如def is_string(obj): try: return isinstance(obj, basestring) # python 2 except NameError: return isinstance(obj, str) # python 3
isaacbernat

19

我发现了这个更多pythonic

if type(aObject) is str:
    #do your stuff here
    pass

由于类型对象是单例,因此可以用于将对象与str类型进行比较


4
由于继承,这不是通用的测试类型的推荐方法:isinstance(obj_to_test, str)显然是为了测试类型,它具有与其他非str案例使用相同过程的优势。
Eric O Lebigot

14

如果一个人想从明确的类型检查(也有说走就走很好的理由远离它),可能是最安全的弦协议的一部分,以检查:

str(maybe_string) == maybe_string

它不会通过迭代的迭代或迭代器,它不会调用列表的串一个字符串,它正确地检测弦乐器的弦。

当然有缺点。例如,str(maybe_string)可能是繁重的计算。通常,答案取决于它

编辑:作为@Tcll 指出的意见,问题实际上询问的方式同时检测unicode字符串和字节串。在Python 2上,此答案将失败,但包含非ASCII字符的unicode字符串将例外,在Python 3上,它将False为所有字节串返回。


对于使用表示形式数据进行初始化的对象,这可能无法按预期方式工作... b = b'test'; r = str(b) == b其中b保存的数据与str(b)(但作为字节对象的)相同,但不能验证为字符串。
Tcll

@Tcll是的,问题实际上是说“常规或Unicode”。我想我没有正确阅读。
clacke

11

为了检查您的变量是否是某些东西,您可以像这样:

s='Hello World'
if isinstance(s,str):
#do something here,

isistance的输出将为您提供布尔值True或False,以便您可以进行相应的调整。您可以通过最初使用以下命令检查您的值的期望首字母缩写:type(s)这将返回您键入“ str”,以便您可以在isistance函数中使用它。


5

我可能会像其他人提到的那样以鸭子打字的方式处理这个问题。我怎么知道一个字符串真的是一个字符串?好吧,显然是通过转换为字符串!

def myfunc(word):
    word = unicode(word)
    ...

如果arg已经是字符串或unicode类型,则real_word将保持其值不变。如果传递的对象实现一个__unicode__方法,则该方法用于获取其unicode表示形式。如果传递的对象不能用作字符串,则unicode内建函数引发异常。


3
isinstance(your_object, basestring)

如果您的对象确实是字符串类型,则将为True。'str'是保留字。

抱歉,正确的答案是使用'basestring'而不是'str',以便它也包括unicode字符串-如上文其他响应者所述。


不适用于在问题中明确要求的unicode对象。
dbn

1

今天晚上,我遇到了一种情况,我以为我必须检查一下str类型,但事实证明我没有。

我解决问题的方法可能在许多情况下都可以使用,因此,在其他阅读此问题的人员感兴趣的情况下,我在下面提供了此方法(仅适用于Python 3)。

# NOTE: fields is an object that COULD be any number of things, including:
# - a single string-like object
# - a string-like object that needs to be converted to a sequence of 
# string-like objects at some separator, sep
# - a sequence of string-like objects
def getfields(*fields, sep=' ', validator=lambda f: True):
    '''Take a field sequence definition and yield from a validated
     field sequence. Accepts a string, a string with separators, 
     or a sequence of strings'''
    if fields:
        try:
            # single unpack in the case of a single argument
            fieldseq, = fields
            try:
                # convert to string sequence if string
                fieldseq = fieldseq.split(sep)
            except AttributeError:
                # not a string; assume other iterable
                pass
        except ValueError:
            # not a single argument and not a string
            fieldseq = fields
        invalid_fields = [field for field in fieldseq if not validator(field)]
        if invalid_fields:
            raise ValueError('One or more field names is invalid:\n'
                             '{!r}'.format(invalid_fields))
    else:
        raise ValueError('No fields were provided')
    try:
        yield from fieldseq
    except TypeError as e:
        raise ValueError('Single field argument must be a string'
                         'or an interable') from e

一些测试:

from . import getfields

def test_getfields_novalidation():
    result = ['a', 'b']
    assert list(getfields('a b')) == result
    assert list(getfields('a,b', sep=',')) == result
    assert list(getfields('a', 'b')) == result
    assert list(getfields(['a', 'b'])) == result

1

它很简单,请使用以下代码(我们假设提到的对象为obj)-

if type(obj) == str:
    print('It is a string')
else:
    print('It is not a string.')

0

您可以通过连接一个空字符串来测试它:

def is_string(s):
  try:
    s += ''
  except:
    return False
  return True

编辑

在指出指出列表失败的评论后纠正我的答案

def is_string(s):
  return isinstance(s, basestring)

您说得对,谢谢您的指出。我给出了一个替代答案。
georgepsarakis 2013年

-3

对于类似字符串的鸭式打字方法,它具有同时使用Python 2.x和3.x的优点:

def is_string(obj):
    try:
        obj + ''
        return True
    except TypeError:
        return False

明智的鱼转而使用鸭式输入法之前就与鸭式输入isinstance方式很接近,只是+=对列表的含义与以前不同+


2
好吧,您有两票赞成票,没有人提供评论。我没有投票,但我不喜欢您的解决方案,因为:*太冗长。您无需定义函数即可执行此操作。*昂贵。捕获异常不利于性能。* 容易出错。其他对象可能实现add,看到一个字符串,并引发另一种类型的异常,它不是TypeError。
santiagobasulto

同样在这里,您将使用鸭式输入法,这种方法很漂亮,但是最终会抛出并捕获异常,只是为了找出不美观的东西。
Alexey Tigarev '16

合法地,这可能是区分类字符串和其他可迭代字符串的唯一肯定方法。可以查找诸如的属性isalpha,但是谁知道可以安全地查找哪些方法?
clacke

意识到__str__加平等的方法实际上可能是万无一失的方法。但是,即便如此,也并非没有警告。
clacke

@santiagobasulto异常在Python中很便宜。如果您预计出现错误的时间为1%,try则可以更快。如果您有99%的期望,也许不是。性能差异很小,最好是习惯性的,除非您分析代码并将其标识为实际上很慢。
尼克T

-4
if type(varA) == str or type(varB) == str:
    print 'string involved'

来自EDX-在线课程MITx:6.00.1x使用Python进行计算机科学和编程简介


6
这可能是最糟糕的检查方法。它不仅排除了unicode对象,还排除了str!的子类。
augurar 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.