¿Cómo saber si un objeto Python es una cadena?


402

¿Cómo puedo verificar si un objeto Python es una cadena (ya sea regular o Unicode)?


18
A lo que Jason se refiere es a escribir pato (si suena como un pato, probablemente sea un pato). En Python, a menudo "deja que su código funcione" en cualquier objeto similar a una cadena sin probar si es una cadena o una subclase de cadenas. Para obtener más información, consulte: docs.python.org/glossary.html#term-duck-typing
Ben Hoyt

44
Eso es lo que me encanta de SO. Usualmente hago una pregunta, no se responde, la gente me dice que no debería estar haciendo eso de todos modos y por qué, y crezco como programador. =)
physicsmichael

24
+1: Solo porque rara vez se necesita una respuesta, no significa que la pregunta no sea válida. Aunque, creo que es genial tener precaución aquí, no creo que merezca degradar la pregunta.
Trevor

17
Este es posiblemente el uso más legítimo de la verificación de tipos en Python. Las cadenas son iterables, por lo que distinguirlas de las listas de cualquier otra forma es una mala idea.
ojrac

3
Definitivamente, hay casos en los que es necesario distinguir cadenas de otros iterables. Por ejemplo, vea el código fuente de PrettyPrinter en el módulo pprint.
saxman01

Respuestas:


302

Python 2

Úselo isinstance(obj, basestring)para un objeto a prueba obj.

Doc .


178

Python 2

Para verificar si un objeto oes un tipo de cadena de una subclase de un tipo de cadena:

isinstance(o, basestring)

porque ambos stry unicodeson subclases de basestring.

Para verificar si el tipo de oes exactamente str:

type(o) is str

Para verificar si oes una instancia stro alguna subclase de str:

isinstance(o, str)

Lo anterior también funciona para cadenas Unicode si lo reemplaza strcon unicode.

Sin embargo, es posible que no necesite hacer una verificación de tipo explícita en absoluto. "Escribir pato" puede satisfacer sus necesidades. Ver http://docs.python.org/glossary.html#term-duck-typing .

Consulte también ¿Cuál es la forma canónica de verificar el tipo en Python?


variable local 'str' referenciada antes de la asignación
john ktejik

@johnktejik python3 vs python2. basestringDebe verificar en py2.
erikbwork

170

Python 3

En Python 3.x basestringya no está disponible, al igual strque el único tipo de cadena (con la semántica de Python 2.x unicode).

Entonces, la comprobación en Python 3.x es solo:

isinstance(obj_to_test, str)

Esto sigue la solución de la 2to3herramienta de conversión oficial : la conversión basestringa str.


94

Python 2 y 3

(compatible con la cruz)

Si desea verificar sin tener en cuenta la versión de Python (2.x vs 3.x), use six( PyPI ) y su string_typesatributo:

import six

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

Dentro de six(un módulo de un solo archivo muy ligero), simplemente está haciendo esto :

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

if PY3:
    string_types = str
else:
    string_types = basestring

Alternativamente, puede usar future( PyPI ) para incluso mantener el nombre:from past.builtins import basestring
David Nemeskey

1
Por cierto, la Cheat Sheet es un gran recurso para la compatibilidad de la versión de Python.
David Nemeskey

1
¿Qué pasa con no usar ninguna importación? Primero intente basestringy luego vuelva a str. Por ejemplodef is_string(obj): try: return isinstance(obj, basestring) # python 2 except NameError: return isinstance(obj, str) # python 3
isaacbernat

19

Encontré esto y más pythonic:

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

dado que los objetos de tipo son singleton, se puede usar para comparar el objeto con el tipo str


44
Esta no es la forma general recomendada de probar el tipo, debido a la herencia: isinstance(obj_to_test, str)obviamente está destinado a probar el tipo, y tiene la ventaja de usar el mismo procedimiento que para otros casos no str.
Eric O Lebigot

14

Si uno quiere mantenerse alejado de explícita el tipo de comprobación (y no son probablemente la parte buenas razones para permanecer lejos de ella), más segura del protocolo cadena a cheque es:

str(maybe_string) == maybe_string

No iterará a través de un iterador o iterador, no llamará a una lista de cadenas una cadena y detecta correctamente una cadena como una cadena.

Por supuesto que hay inconvenientes. Por ejemplo, str(maybe_string)puede ser un cálculo pesado. Como tantas veces, la respuesta es que depende .

EDITAR: como @Tcll señala en los comentarios, la pregunta realmente pide una forma de detectar tanto cadenas unicode como cadenas de bytes. En Python 2, esta respuesta fallará con una excepción para las cadenas unicode que contienen caracteres no ASCII, y en Python 3 devolverá Falsetodas las cadenas de bytes.


En el caso de los objetos que se inicializan con datos de representación, esto puede no funcionar como se esperaba ... b = b'test'; r = str(b) == bdonde bcontiene los mismos datos str(b)pero (al ser un objeto de bytes) no se valida como una cadena.
Tcll

@Tcll Correcto, la pregunta en realidad dice "regular o Unicode". Supongo que no lo leí correctamente.
clacke

11

Para verificar si su variable es algo que podría usar:

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

La salida de isistance le dará un valor booleano verdadero o falso para que pueda ajustar en consecuencia. Puede verificar el acrónimo esperado de su valor usando inicialmente: tipo (s) Esto le devolverá el tipo 'str' para que pueda usarlo en la función de resistencia.


5

Podría lidiar con esto en el estilo de escritura de pato, como mencionan otros. ¿Cómo sé que una cadena es realmente una cadena? bueno, obviamente al convertirlo en una cadena!

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

Si el argumento ya es una cadena o un tipo unicode, real_word mantendrá su valor sin modificar. Si el objeto pasado implementa un __unicode__método, que se utiliza para obtener su representación unicode. Si el objeto pasado no se puede usar como una cadena, el valor unicodeincorporado genera una excepción.


3
isinstance(your_object, basestring)

será True si su objeto es realmente un tipo de cadena. 'str' es una palabra reservada.

Mis disculpas, la respuesta correcta es usar 'basetring' en lugar de 'str' para que también incluya cadenas unicode, como se señaló anteriormente por uno de los otros respondedores.


No funciona para objetos unicode, que se solicitaron explícitamente en la pregunta.
dbn

1

Esta tarde me encontré con una situación en la que pensé que iba a tener que verificar el strtipo, pero resultó que no.

Mi enfoque para resolver el problema probablemente funcionará en muchas situaciones, por lo que lo ofrezco a continuación en caso de que otras personas que lean esta pregunta estén interesadas (solo 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

Algunas pruebas:

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

Es simple, use el siguiente código (asumimos que el objeto mencionado es obj):

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

0

Puede probarlo concatenando con una cadena vacía:

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

Editar :

Corregir mi respuesta después de comentarios que señalan que esto falla con las listas

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

Tienes razón, gracias por señalarlo. He dado una respuesta alternativa.
georgepsarakis

-3

Para un buen enfoque de tipeo de pato para me gusta de cadenas que tiene la ventaja de trabajar con Python 2.xy 3.x:

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

wisefish estaba cerca del tipeo de patos antes de cambiar al isinstanceenfoque, excepto que +=tiene un significado diferente para las listas que el que +tiene.


2
Bueno, tienes dos votos negativos y nadie hizo ningún comentario. No he votado negativamente pero no me gusta su solución porque: * Demasiado detallado. No debería necesitar definir una función para hacer esto. * Costoso. Capturar excepciones no es bueno para el rendimiento. * Propenso a errores. Otro objeto podría implementar agregar , ver una cadena y generar otro tipo de excepción, que no es TypeError.
santiagobasulto

También aquí está empleando el enfoque de tipeo de pato, que es hermoso, pero termina con la excepción de lanzar y atrapar solo para descubrir algo que no es hermoso.
Alexey Tigarev

Esta puede ser legítimamente la única forma segura de distinguir entre una cadena similar a una cadena y alguna otra iterable de cadena. Uno podría buscar atributos como isalpha, pero ¿quién sabe qué métodos sería seguro buscar?
clacke

Me di cuenta de que el __str__método más la igualdad en realidad puede ser el infalible. Pero incluso eso no está exento de advertencias.
clacke

Las excepciones de @santiagobasulto son baratas en Python. Si espera el error el 1% del tiempo, trypuede ser más rápido. Si lo espera el 99% del tiempo, tal vez no. La diferencia de rendimiento es mínima, es mejor ser idiomático a menos que perfiles tu código y lo identifiques como lento.
Nick T

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

de EDX - curso en línea MITx: 6.00.1x Introducción a la informática y programación usando Python


66
Esta es probablemente la peor forma posible de verificar. No solo excluye objetos unicode, ¡incluso excluye subclases de str!
augurar
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.