Cómo verificar si la variable es una cadena con compatibilidad con python 2 y 3


171

Soy consciente de que puedo usar: isinstance(x, str)en python-3.x, pero también necesito verificar si algo es una cadena en python-2.x. ¿ isinstance(x, str)Funcionará como se esperaba en python-2.x? ¿O tendré que verificar la versión y usarla isinstance(x, basestr)?

Específicamente, en python-2.x:

>>>isinstance(u"test", str)
False

y python-3.x no tiene u"foo"


2
La sintaxis u "" para literales Unicode se reintroduce en Python 3.3
— jfs

Impar. Obtengo `` `>>> isinstance (u" test ", basetring) True` `` en Python 2.7.16
— Darakian

Respuestas:


209

Si está escribiendo código compatible con 2.xy 3.x, probablemente quiera usar seis :

from six import string_types
isinstance(s, string_types)

Lo siento, estoy un poco confundido sobre el siguiente resultado. >>> isinstance(u"foo", string_types) True >>> isinstance(u"foo".encode("utf-8"), string_types) True Esperaba que isinstance (u "foo", string_types) devuelva false.
— Chandler.Huang

1
@ Chandler.Huang, esta pregunta se trata de identificar stry unicodeen Python 2, o stren Python 3. Si no desea unicodecontar con Python 2, simplemente use str.
— ecatmur

@ecatmur woops, gracias! lo eliminó, para que nadie se confunda
— runDOSrun

44
también puede usarlo desde el futurepaquete en lugar de six:from future.utils import string_types
— SuperGeo

113

El enfoque más conciso que he encontrado sin depender de paquetes como seis, es:

try:
  basestring
except NameError:
  basestring = str

luego, suponiendo que haya estado buscando cadenas en Python 2 de la manera más genérica,

isinstance(s, basestring)

ahora también funcionará para Python 3+.


10
Para py3, basestring = (str, bytes)derequests/compat.py
— Tanky Woo

Bien, pero ¿por qué? Sería bueno si Python3 fuera compatible con versiones anteriores aquí. Las soluciones anteriores funcionan. Sería aún mejor, si no fuera necesario.
— guettli

2
Para satisfacer tanto el soporte de py2 & 3 como mypy, terminé conif not hasattr(__builtins__, "basestring"): basestring = (str, bytes)
— Dave Lee

35

¿Qué pasa con esto, funciona en todos los casos?

isinstance(x, ("".__class__, u"".__class__))

@holdenweb: No y sí, creo que un ingenioso truco "solo impacta donde sea necesario".
— Dilettant

1
La razón por la que me gusta esta respuesta es que es amigable con la migración de python2 a 3.
— Tiagojdferreira

44
También utilicé esta opción, envolviéndola en una función auxiliar, por lo que solo aparece una vez, y hay un lugar en la cadena de documentación para acreditar a Fil.
— Carl Smith

2
Aseado, y lo estaba usando yo mismo, hasta que me di cuenta de que también tenía from __future__ import unicode_literalsactivo. Ahora voy con:isinstance(val, (str, u"".__class__))
— Graham Klyne

18

Esta es la respuesta de @Lev Levitsky, reescrita un poco.

try:
    isinstance("", basestring)
    def isstr(s):
        return isinstance(s, basestring)
except NameError:
    def isstr(s):
        return isinstance(s, str)

La prueba try/ exceptse realiza una vez y luego define una función que siempre funciona y es lo más rápida posible.

EDITAR: En realidad, ni siquiera necesitamos llamar isinstance(); solo necesitamos evaluar basestringy ver si obtenemos un NameError:

try:
    basestring  # attempt to evaluate basestring
    def isstr(s):
        return isinstance(s, basestring)
except NameError:
    def isstr(s):
        return isinstance(s, str)

Sin embargo, creo que es más fácil seguir con la llamada isinstance().


isinstance("", basestring)es lo que quise decir con "llamar". De todos modos, +1.
— Lev Levitsky

1
Python es un lenguaje muy dinámico, y no creo que se vea nada mal tener una prueba como esa. Esta es una técnica útil para resolver algo una vez, y en base a eso, configurar una función que siempre será correcta. Gracias por el +1.
— steveha

55
Lo escribiría como:try: string_types = basestring except NameError: string_types = str
— jfs

12

La futurebiblioteca agrega (a Python 2) nombres compatibles , por lo que puede continuar escribiendo Python 3 . Simplemente puede hacer lo siguiente:

from builtins import str
isinstance(x, str) 

Para instalarlo , solo ejecute pip install future.

Como advertencia , solo es compatible python>=2.6, >=3.3pero es más moderno que six, lo que solo se recomienda si se usapython 2.5


8

Tal vez use una solución como

def isstr(s):
    try:
        return isinstance(s, basestring)
    except NameError:
        return isinstance(s, str)

Lamento molestarlo, pero me isinstance(u'hello', basestr)rinde SyntaxError: invalid syntaxcon Python 3.2.3 en la Ventana 7 ... ¿alguna idea de por qué esto sería? Parece que no le gusta el u- Me sale este error con strybasestr
— Levon

1
@Levon No hay problema :) Eso es porque Python3 no tiene esa sintaxis , ya que stren Python3 es, por definición, Unicode. En consecuencia, no hay ningún basestringtipo, por lo tanto, eso NameErrorestá atrapado en mi fragmento.
— Lev Levitsky

Tiene esa sintaxis como noop ahora. en 3.3
— Randall Hunt

2
Sugeriría hacer la prueba try/ exceptuna sola vez, y en función de los resultados de esa prueba única, usted define isstr()correctamente. No es necesario incurrir en la sobrecarga de una excepción por cada llamada a isstr().
— steveha

@Ranman tiene razón sobre Python 3.3, aquí hay un enlace a la PEP .
— Lev Levitsky

7

Puede obtener la clase de un objeto llamando object.__class__, por lo que para verificar si el objeto es el tipo de cadena predeterminado:

    isinstance(object,"".__class__)

Y puede colocar lo siguiente en la parte superior de Su código para que las cadenas entre comillas estén en unicode en python 2:

    from __future__ import unicode_literals

Yo esta solución bastante. Descubrí que puede ser útil definir str = "" .__ class__, que ahora permite que isinstance (objeto, str) se escriba normalmente, y también garantiza que str (objeto) devolverá una cadena unicode en Python 2 y Python 3.
— amicitas

Esto no funciona al analizar XML: some_element.textes un 'str' pero la comparación con 'unicode' fallaría
— bóveda

No funciona con cadena Unicode en python 2: isinstance (u'XXX ',' '.__ class__) == False
— Fil

0

Puedes probar esto al comienzo de tu código:

from __future__ import print_function
import sys
if sys.version[0] == "2":
    py3 = False
else:
    py3 = True
if py3: 
    basstring = str
else:
    basstring = basestring

y luego en el código:

anystring = "test"
# anystring = 1
if isinstance(anystring, basstring):
    print("This is a string")
else:
    print("No string")

0

¡Ten cuidado! En python 2, stry bytesson esencialmente lo mismo. Esto puede causar un error si está tratando de distinguir entre los dos.

>>> size = 5    
>>> byte_arr = bytes(size)
>>> isinstance(byte_arr, bytes)
True
>>> isinstance(byte_arr, str)
True

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.