Como descobrir se um objeto Python é uma string?


402

Como posso verificar se um objeto Python é uma string (regular ou Unicode)?


18
O que Jason está se referindo é digitação de pato (se grasna como um pato, provavelmente é um pato). No Python, você costuma "deixar seu código funcionar" em qualquer objeto semelhante a uma string sem testar se é uma subclasse de string ou string. Para obter mais informações, consulte: docs.python.org/glossary.html#term-duck-typing
Ben Hoyt

4
Isso é o que eu amo no SO. Geralmente faço uma pergunta, ela não é respondida, as pessoas me dizem que eu não deveria fazer isso de qualquer maneira e por quê, e eu cresci como programador. =)
physicsmichael

24
+1: apenas porque uma resposta raramente é necessária, não significa que a pergunta é inválida. Embora eu ache ótimo ter cautela aqui, acho que não merece rebaixar a questão.
Trevor

17
Esse é possivelmente o uso mais legítimo da verificação de tipo no Python. As strings são iteráveis, portanto, distingui-las das listas de qualquer outra maneira é uma má idéia.
ojrac

3
Definitivamente, há casos em que é necessário distinguir seqüências de caracteres de outros iteráveis. Por exemplo, consulte o código fonte do PrettyPrinter no módulo pprint.
saxman01

Respostas:



178

Python 2

Para verificar se um objeto oé um tipo de string de uma subclasse de um tipo de string:

isinstance(o, basestring)

porque ambos stre unicodesão subclasses de basestring.

Para verificar se o tipo de oé exatamente str:

type(o) is str

Para verificar se oé uma instância strou qualquer subclasse de str:

isinstance(o, str)

O exemplo acima também funciona para cadeias de caracteres Unicode, se você substituir strpor unicode.

No entanto, talvez você não precise fazer nenhuma verificação explícita de tipo. A "digitação do pato" pode atender às suas necessidades. Veja http://docs.python.org/glossary.html#term-duck-typing .

Consulte também Qual é a maneira canônica de verificar o tipo em python?


variável local 'str' referenciada antes da atribuição
john ktejik 30/10

@johnktejik python3 vs python2. Você precisa verificar basestringem py2.
precisa saber é o seguinte

170

Python 3

No Python 3.x, basestringnão está mais disponível, como stré o único tipo de string (com a semântica do Python 2.x unicode).

Portanto, a verificação no Python 3.x é apenas:

isinstance(obj_to_test, str)

Isso segue a correção da 2to3ferramenta de conversão oficial : converter basestringpara str.


94

Python 2 e 3

(compatível com outras versões)

Se você deseja verificar sem considerar a versão do Python (2.x vs 3.x), use six( PyPI ) e seu string_typesatributo:

import six

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

Dentro six(um módulo de arquivo único muito leve), basta fazer o seguinte :

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

if PY3:
    string_types = str
else:
    string_types = basestring

Como alternativa, você pode usar future( PyPI ) para manter o nome:from past.builtins import basestring
David Nemeskey 8/17/17

11
BTW the Cheat Sheet é um ótimo recurso para compatibilidade com a versão Python.
9137 David Nemeskey

11
Que tal não usar nenhuma importação? Primeiro tente basestringe depois volte para str. Por exemplodef is_string(obj): try: return isinstance(obj, basestring) # python 2 except NameError: return isinstance(obj, str) # python 3
isaacbernat 13/08

19

Encontrei isso e mais pythonic:

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

desde que os objetos de tipo são Singleton, é pode ser usado para fazer a comparar o objeto para o tipo str


4
Esta não é a maneira geral recomendada de teste para o tipo, devido à herança: isinstance(obj_to_test, str)obviamente é para testar o tipo e tem a vantagem de usar o mesmo procedimento que para outros casos não-str.
Eric O Lebigot

14

Se alguém quiser ficar longe explícita (e não de verificação de tipo são , provavelmente, a parte mais segura boas razões para ficar longe dele) do protocolo de string para verificação é:

str(maybe_string) == maybe_string

Ele não itera através de um iterável ou iterador, não chama uma lista de cadeias de caracteres como uma string e detecta corretamente uma string como uma string.

Claro que existem desvantagens. Por exemplo, str(maybe_string)pode ser um cálculo pesado. Como tantas vezes, a resposta é que depende .

EDIT: Como o @Tcll aponta nos comentários, a pergunta realmente pede uma maneira de detectar cadeias unicode e bytestrings. No Python 2, esta resposta falhará, com uma exceção para cadeias unicode que contêm caracteres não ASCII, e no Python 3 retornará Falsepara todas as cadeias de bytes.


No caso de objetos que são inicializados com dados de representação, isso pode não funcionar conforme o esperado ... b = b'test'; r = str(b) == bonde bmantém os mesmos dados que str(b)mas (sendo um objeto de bytes) não valida como uma sequência.
Tcll

@ Tcll Certo, a pergunta realmente diz "regular ou Unicode". Acho que não li direito.
clacke 04/01

11

Para verificar se sua variável é algo que você pode usar:

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

A saída de isistance fornecerá um valor booleano True ou False, para que você possa ajustar adequadamente. Você pode verificar o acrônimo esperado do seu valor usando inicialmente: type (s) Isso retornará o tipo 'str' para que você possa usá-lo na função isistance.


5

Eu posso lidar com isso no estilo de digitação de pato, como outros mencionam. Como sei que uma string é realmente uma string? bem, obviamente, convertendo -o em uma string!

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

Se o arg já for um tipo de cadeia ou unicode, real_word manterá seu valor não modificado. Se o objeto transmitido implementa um __unicode__método, isso é usado para obter sua representação unicode. Se o objeto passado não puder ser usado como uma sequência, o unicodebuiltin gerará uma exceção.


3
isinstance(your_object, basestring)

será True se o seu objeto for realmente um tipo de string. 'str' é uma palavra reservada.

minhas desculpas, a resposta correta é usar 'basestring' em vez de 'str' para incluir também strings unicode - como observado acima por um dos outros respondedores.


Não funciona para objetos unicode, que foram explicitamente solicitados na pergunta.
dbn

1

Naquela noite, me deparei com uma situação em que achava que precisaria checar o strtipo, mas acabou que não.

Minha abordagem para resolver o problema provavelmente funcionará em muitas situações, por isso ofereço-o abaixo caso outras pessoas que estejam lendo esta questão estejam interessadas (somente 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

Alguns testes:

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

É simples, use o seguinte código (assumimos que o objeto mencionado seja obj) -

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

0

Você pode testá-lo concatenando com uma sequência vazia:

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

Editar :

Corrigindo minha resposta após comentários apontando que isso falha nas listas

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

Você está certo, obrigado por apontar. Eu dei uma resposta alternativa.
Georgepsarakis

-3

Para uma boa abordagem de digitação de pato para curtidas de string que tem o bônus de trabalhar com o Python 2.xe 3.x:

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

o wisefish estava próximo da digitação do pato antes de mudar para a isinstanceabordagem, exceto que ele +=tem um significado diferente para as listas +.


2
Bem, você tem dois votos negativos e ninguém forneceu um comentário. Não diminuí a votação, mas não gosto da sua solução porque: * Muito detalhado. Você não precisa definir uma função para fazer isso. * Caro. Capturar exceções não é bom para o desempenho. * Erro propenso. Outro objeto pode implementar adicionar , ver uma sequência e gerar outro tipo de exceção, que não é TypeError.
315915 santiagobasulto

Também aqui você está empregando a abordagem de digitação de pato, que é bonita, mas acaba lançando e capturando exceções apenas para descobrir algo que não é bonito.
Alexey Tigarev

Essa pode ser legitimamente a única maneira infalível de distinguir entre uma string e outra iterável. Pode-se procurar atributos como isalpha, mas quem sabe que métodos seriam seguros?
Clacke

Eu percebi que o __str__método mais igualdade pode realmente ser a única prova de idiota. Mas mesmo isso não é sem ressalvas.
Clacke

As exceções do @santiagobasulto são baratas no Python. Se você espera o erro 1% do tempo, trypode ser mais rápido. Se você espera 99% do tempo, talvez não. Como a diferença de desempenho é mínima, é melhor ser idiomático, a menos que você crie um perfil do seu código e o identifique como realmente lento.
Nick T

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

from EDX - curso online MITx: 6.00.1x Introdução à ciência da computação e programação usando Python


6
Esta é provavelmente a pior maneira possível de verificar. Não apenas exclui objetos unicode, como também exclui subclasses de str!
218
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.