Come scoprire se un oggetto Python è una stringa?


402

Come posso verificare se un oggetto Python è una stringa (normale o Unicode)?


18
Ciò a cui Jason si riferisce è la tipizzazione delle anatre (se si rompe come un'anatra probabilmente è un'anatra). In Python spesso "fai funzionare il tuo codice" su qualsiasi oggetto simile a una stringa senza verificare se si tratta di una sottoclasse di stringa o stringa. Per maggiori informazioni, consultare: docs.python.org/glossary.html#term-duck-typing
Ben Hoyt

4
Questo è ciò che amo di SO. Di solito faccio una domanda, non mi viene data risposta, la gente mi dice che non dovrei farlo comunque e perché, e cresco come programmatore. =)
Physicsmichael,

24
+1: solo perché raramente è necessaria una risposta, non significa che la domanda non sia valida. Anche se, penso che sia bello avere un'attenzione qui, non penso che meriti di sminuire la domanda.
Trevor,

17
Questo è probabilmente l'uso più legittimo del controllo del tipo in Python. Le stringhe sono iterabili, quindi distinguerle dagli elenchi in altro modo è una cattiva idea.
ojrac,

3
Esistono sicuramente casi in cui è necessario distinguere le stringhe da altri iterabili. Ad esempio, vedere il codice sorgente per PrettyPrinter nel modulo pprint.
saxman01,

Risposte:


302

Python 2

Utilizzare isinstance(obj, basestring)per un oggetto da testare obj.

Doc .


178

Python 2

Per verificare se un oggetto oè un tipo di stringa di una sottoclasse di un tipo di stringa:

isinstance(o, basestring)

perché entrambi stre unicodesono sottoclassi di basestring.

Per verificare se il tipo di oè esattamente str:

type(o) is str

Per verificare se oè un'istanza stro una sottoclasse di str:

isinstance(o, str)

Quanto sopra funziona anche per le stringhe Unicode se si sostituisce strcon unicode.

Tuttavia, potrebbe non essere necessario eseguire alcun controllo esplicito del tipo. "Duck typing" può soddisfare le tue esigenze. Vedi http://docs.python.org/glossary.html#term-duck-typing .

Vedi anche Qual è il modo canonico per controllare il tipo in Python?


variabile locale "str" ​​a cui si fa riferimento prima dell'incarico
john ktejik,

@johnktejik python3 vs python2. Devi controllare basestringin py2.
erikbwork,

170

Python 3

In Python 3.x basestringnon è più disponibile, così come strl'unico tipo di stringa (con la semantica di Python 2.x unicode).

Quindi il controllo in Python 3.x è solo:

isinstance(obj_to_test, str)

Questo segue la correzione dello 2to3strumento di conversione ufficiale : conversione basestringin str.


94

Python 2 e 3

(Compatibile-cross)

Se vuoi controllare senza riguardo per la versione di Python (2.x vs 3.x), usa six( PyPI ) e il suo string_typesattributo:

import six

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

All'interno six(un modulo a file singolo molto leggero), sta semplicemente facendo questo :

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

if PY3:
    string_types = str
else:
    string_types = basestring

In alternativa, puoi usare future( PyPI ) anche per mantenere il nome:from past.builtins import basestring
David Nemeskey

1
A proposito, il Cheat Sheet è un'ottima risorsa per la compatibilità della versione di Python.
David Nemeskey,

1
Che dire di non utilizzare alcuna importazione? Prima prova basestringe poi torna a str. Ad esempiodef is_string(obj): try: return isinstance(obj, basestring) # python 2 except NameError: return isinstance(obj, str) # python 3
Isaacbernat,

19

Ho trovato questo ans altro pythonic:

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

dato che gli oggetti di tipo sono singoletto, è può essere usato per fare il confronto l'oggetto nel tipo str


4
Questo non è il modo generale raccomandato di testare il tipo, a causa dell'ereditarietà: isinstance(obj_to_test, str)è ovviamente pensato per testare il tipo e ha il vantaggio di usare la stessa procedura di altri casi non str.
Eric O Lebigot,

14

Se si vuole evitare il controllo esplicito del tipo (e ci sono buoni motivi per starne alla larga), probabilmente la parte più sicura del protocollo di stringa da controllare è:

str(maybe_string) == maybe_string

Non itererà attraverso un iterabile o un iteratore, non chiamerà un elenco di stringhe una stringa e rileva correttamente una stringa simile a una stringa.

Naturalmente ci sono degli svantaggi. Ad esempio, str(maybe_string)può essere un calcolo pesante. Come spesso accade, la risposta è che dipende .

EDIT: Come sottolinea @Tcll nei commenti, la domanda in realtà chiede un modo per rilevare sia stringhe unicode che bytestring. Su Python 2 questa risposta fallirà con un'eccezione per le stringhe unicode che contengono caratteri non ASCII, e su Python 3 tornerà per tutte le esclusioni.False


Nel caso di oggetti che si inizializzano con dati di rappresentazione, questo potrebbe non funzionare come previsto ... b = b'test'; r = str(b) == bdove bcontiene gli stessi dati di str(b)ma (essendo un oggetto byte) non convalida come una stringa.
Fino al

@Tcll Bene, la domanda in realtà dice "normale o Unicode". Immagino di non averlo letto correttamente.
clacke il

11

Per verificare se la tua variabile è qualcosa potresti andare come:

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

L'output di isistance ti darà un valore Vero o Falso booleano in modo che tu possa adeguarti di conseguenza. Puoi verificare l'acronimo atteso del tuo valore inizialmente usando: type (s) Questo ti restituirà il tipo 'str' in modo da poterlo usare nella funzione isistance.


5

Potrei occuparmene nello stile di scrivere l'anatra, come altri citano. Come faccio a sapere che una stringa è davvero una stringa? bene, ovviamente convertendolo in una stringa!

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

Se arg è già una stringa o un tipo unicode, real_word manterrà il suo valore non modificato. Se l'oggetto passato implementa un __unicode__metodo, viene utilizzato per ottenere la sua rappresentazione unicode. Se l'oggetto passato non può essere utilizzato come stringa, il unicodecomando incorporato genera un'eccezione.


3
isinstance(your_object, basestring)

sarà True se il tuo oggetto è effettivamente un tipo di stringa. 'str' è una parola riservata.

mi scuso, la risposta corretta sta usando "basestring" anziché "str" ​​per includere anche stringhe unicode - come è stato notato sopra da uno degli altri responder.


Non funziona per gli oggetti Unicode, che sono stati esplicitamente richiesti nella domanda.
dbn

1

Questa sera mi sono imbattuto in una situazione in cui pensavo che avrei dovuto verificare il strtipo, ma alla fine non l'ho fatto.

Il mio approccio alla risoluzione del problema probabilmente funzionerà in molte situazioni, quindi lo offro di seguito nel caso in cui altri che leggono questa domanda siano interessati (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

Alcuni test:

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

È semplice, usa il seguente codice (assumiamo che l'oggetto indicato sia obj) -

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

0

Puoi testarlo concatenandolo con una stringa vuota:

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

Modifica :

Correzione della mia risposta dopo i commenti che sottolineano che ciò fallisce con gli elenchi

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

Hai ragione, grazie per averlo sottolineato. Ho dato una risposta alternativa.
georgepsarakis,

-3

Per un simpatico approccio alla tipizzazione di anatre per stringhe che ha il vantaggio di lavorare con Python 2.xe 3.x:

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

wisefish era vicino alla tipizzazione delle anatre prima di passare isinstanceall'approccio, tranne per il fatto che +=ha un significato diverso per le liste rispetto a quello +.


2
Bene, hai due voti negativi e nessuno ha fornito un commento. Non ho effettuato il downgrade ma non mi piace la tua soluzione perché: * Troppo prolisso. Non è necessario definire una funzione per farlo. * Costoso. Catturare le eccezioni non è buono per le prestazioni. * Incline a errori. Un altro oggetto potrebbe implementare add , vedere una stringa e sollevare un altro tipo di eccezione, che non è TypeError.
santiagobasulto,

Anche qui stai usando l'approccio alla tipizzazione delle anatre, che è bello, ma finisci col lanciare e catturare l'eccezione solo per scoprire qualcosa, che non è bello.
Alexey Tigarev,

Questo può essere legittimamente l'unico modo infallibile per distinguere tra una stringa simile a una stringa e qualche altra iterabile di stringa. Si potrebbero cercare attributi come isalpha, ma chissà quali metodi sarebbe sicuro cercare?
clacke,

Mi sono reso conto che il __str__metodo più l'uguaglianza potrebbe effettivamente essere a prova di errore. Ma anche quello non è senza avvertimenti.
clacke,

Le eccezioni di @santiagobasulto sono economiche in Python. Se ti aspetti l'errore l'1% delle volte, trypuò essere più veloce. Se te lo aspetti il ​​99% delle volte, forse no. La differenza di prestazioni è minima, è meglio essere idiomatici se non si profila il codice e lo si identifica come effettivamente lento.
Nick T,

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

da EDX - corso online MITx: 6.00.1x Introduzione all'informatica e alla programmazione con Python


6
Questo è probabilmente il modo peggiore per verificare. Non solo esclude gli oggetti Unicode, ma esclude anche le sottoclassi di str!
agosto
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.