Come verificare se la variabile è stringa con compatibilità python 2 e 3


171

Sono consapevole di poter usare: isinstance(x, str)in python-3.x ma devo verificare se qualcosa è una stringa anche in python-2.x. Funzionerà isinstance(x, str)come previsto in Python-2.x? O dovrò controllare la versione e usarla isinstance(x, basestr)?

In particolare, in python-2.x:

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

e python-3.x non ha u"foo"


2
u "" la sintassi per i letterali Unicode viene reintrodotta in Python 3.3
jfs il

Dispari. Ottengo `` >>> isinstance (u "test", basestring) True `` `su Python 2.7.16
Darakian,

Risposte:


209

Se stai scrivendo un codice compatibile con 2.xe 3.x, probabilmente vorrai usare sei :

from six import string_types
isinstance(s, string_types)

Scusa, sono un po 'confuso riguardo al seguente risultato. >>> isinstance(u"foo", string_types) True >>> isinstance(u"foo".encode("utf-8"), string_types) True Mi aspettavo che isinstance (u "foo", string_types) restituisse false.
Chandler

1
@ Chandler. Questa domanda riguarda l'identificazione stre unicodesu Python 2 o strsu Python 3. Se non vuoi unicodecontare su Python 2, usa semplicemente str.
ecatmur

@ecatmur woops, grazie! cancellato, così nessuno si confonde
esegui DOSrun il

4
puoi anche usarlo dal futurepacchetto anziché six:from future.utils import string_types
SuperGeo

113

L'approccio più conciso che ho trovato senza fare affidamento su pacchetti come sei, è:

try:
  basestring
except NameError:
  basestring = str

quindi, supponendo che tu abbia verificato le stringhe in Python 2 nel modo più generico,

isinstance(s, basestring)

ora funzionerà anche con Python 3+.


10
Per py3, basestring = (str, bytes)darequests/compat.py
Tanky Woo,

Bello, ma perché? Sarebbe bello se Python3 fosse retrocompatibile qui. Le soluzioni sopra funzionano. Sarebbe ancora meglio, se non ce ne fosse bisogno.
Guettli,

2
Per soddisfare sia PY2 e 3 di supporto e mypy, ho finito conif not hasattr(__builtins__, "basestring"): basestring = (str, bytes)
Dave Lee

35

Che dire di questo, funziona in tutti i casi?

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

@holdenweb: No e sì, credo che un trucco "influisce solo dove serve".
Dilettant

1
Il motivo per cui mi piace questa risposta è che è amichevole con la migrazione da Python2 a 3.
Tiagojdferreira,

4
Ho anche scelto questa opzione, avvolgendola in una funzione di supporto, quindi appare solo una volta, e c'è un posto nella documentazione per accreditare Fil.
Carl Smith,

2
Pulito, e lo stavo usando da solo, fino a quando mi sono reso conto che anch'io sono from __future__ import unicode_literalsattivo. Ora vado con:isinstance(val, (str, u"".__class__))
Graham Klyne il

18

Questa è la risposta di Lev Levky, riscritta un po '.

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

Il try/ excepttest viene eseguito una volta, quindi definisce una funzione che funziona sempre ed è il più veloce possibile.

EDIT: In realtà, non abbiamo nemmeno bisogno di chiamare isinstance(); dobbiamo solo valutare basestringe vedere se otteniamo un NameError:

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

Penso che sia più facile seguire la chiamata a isinstance(), comunque.


isinstance("", basestring)è ciò che intendevo per "chiamare". Comunque, +1.
Lev Levitsky,

1
Python è un linguaggio molto dinamico e non credo affatto che abbia un test del genere. Questa è una tecnica utile per capire qualcosa una volta, e sulla base di ciò, impostare una funzione che sarà sempre corretta. Grazie per il +1.
Steveha,

5
Lo scriverei come:try: string_types = basestring except NameError: string_types = str
jfs il

12

La futurelibreria aggiunge (a Python 2) nomi compatibili , in modo da poter continuare a scrivere Python 3 . Puoi semplicemente fare quanto segue:

from builtins import str
isinstance(x, str) 

Per installarlo , basta eseguire pip install future.

Come un avvertimento , ma solo il supporto python>=2.6, >=3.3ma è più moderno rispetto six, che è solo consigliato se si utilizzapython 2.5


8

Forse usare una soluzione alternativa come

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

Mi dispiace disturbarti ma isinstance(u'hello', basestr)cedo SyntaxError: invalid syntaxper me con Python 3.2.3 sotto Window 7 .. hai idea del perché questo sarebbe? Non mi piace il u- Ricevo questo errore con strebasestr
Levon

1
@Levon Nessun problema :) Questo perché Python3 non ha quella sintassi , come strin Python3 è per definizione Unicode. Di conseguenza, non esiste alcun basestringtipo, quindi quello NameErrorche viene catturato nel mio frammento.
Lev Levitsky,

Ora ha questa sintassi come noop. in 3.3
Randall Hunt il

2
Suggerirei di eseguire il try/ excepttest una sola volta e, in base ai risultati di quel singolo test, lo definisci isstr()correttamente. Non è necessario incorrere nel sovraccarico di un'eccezione per ogni chiamata a isstr().
Steveha,

@Ranman ha ragione su Python 3.3, ecco un link al PEP .
Lev Levitsky,

7

Puoi ottenere la classe di un oggetto chiamando object.__class__, quindi per verificare se l'oggetto è il tipo di stringa predefinito:

    isinstance(object,"".__class__)

E puoi inserire quanto segue nella parte superiore del tuo codice in modo che le stringhe racchiuse tra virgolette siano in Unicode in Python 2:

    from __future__ import unicode_literals

Ho questa soluzione un bel po '. Ho scoperto che può essere utile definire str = "" .__ class__, che ora consente a isinstance (oggetto, str) di essere scritto normalmente e garantisce anche che str (oggetto) restituisca una stringa unicode sia in Python 2 che in Python 3.
amicitas,

Questo non funziona quando analizza XML: some_element.textè uno 'str' ma il confronto con 'unicode' fallirebbe
vault

Non funziona con la stringa Unicode su Python 2: isinstance (u'XXX ',' '.__ class__) == False
Fil

0

Puoi provare questo all'inizio del tuo codice:

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

e più avanti nel codice:

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

0

Stai attento! In Python 2, stre bytessono essenzialmente gli stessi. Ciò può causare un bug se si sta tentando di distinguere tra i due.

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

-4

tipo (stringa) == str

restituisce true se è una stringa e false in caso contrario


1
Non è vero per Python 2, dove stringè presente una stringa unicode
lxop
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.