Wie finde ich heraus, ob ein Python-Objekt eine Zeichenfolge ist?

402

Wie kann ich überprüfen, ob ein Python-Objekt eine Zeichenfolge ist (entweder regulär oder Unicode)?

Matt S.
quelle
18
Was Jason meint, ist das Tippen von Enten (wenn es wie eine Ente quakt, ist es wahrscheinlich eine Ente). In Python lassen Sie Ihren Code häufig an einem stringähnlichen Objekt "arbeiten", ohne zu testen, ob es sich um einen String oder eine String-Unterklasse handelt. Weitere Informationen finden Sie unter: docs.python.org/glossary.html#term-duck-typing
Ben Hoyt
4
Das liebe ich an SO. Normalerweise stelle ich eine Frage, die nicht beantwortet wird. Die Leute sagen mir, ich sollte das sowieso nicht tun und warum, und ich wachse als Programmierer. =)
Physikmichael
24
+1: Nur weil eine Antwort selten benötigt wird, heißt das nicht, dass die Frage ungültig ist. Obwohl ich es toll finde, hier Vorsicht walten zu lassen, halte ich es nicht für sinnvoll, die Frage herabzusetzen.
Trevor
17
Dies ist möglicherweise die legitimste Verwendung der Typprüfung in Python. Zeichenfolgen sind iterierbar, daher ist es eine schlechte Idee, sie auf andere Weise von Listen zu unterscheiden.
Ojrac
3
Es gibt definitiv Fälle, in denen es notwendig ist, Zeichenfolgen von anderen iterablen Elementen zu unterscheiden. Siehe beispielsweise den Quellcode für PrettyPrinter im pprint-Modul.
Saxman01

Antworten:

302

Python 2

Verwenden Sie isinstance(obj, basestring)für ein zu testendes Objekt obj.

Docs .

John Fouhy
quelle
178

Python 2

So überprüfen Sie, ob ein Objekt oein Zeichenfolgentyp einer Unterklasse eines Zeichenfolgentyps ist:

isinstance(o, basestring)

weil beide strund unicodeUnterklassen von sind basestring.

So überprüfen Sie, ob der Typ ogenau ist str:

type(o) is str

So überprüfen Sie, ob oes sich um eine Instanz stroder eine Unterklasse von str:

isinstance(o, str)

Die oben auch Arbeit für Unicode - Strings , wenn Sie ersetzen strmit unicode.

Möglicherweise müssen Sie jedoch überhaupt keine explizite Typprüfung durchführen. "Duck Typing" kann Ihren Bedürfnissen entsprechen. Siehe http://docs.python.org/glossary.html#term-duck-typing .

Siehe auch Wie kann kanonisch nach Python gesucht werden?

Matt S.
quelle
lokale Variable 'str', auf die vor der Zuweisung
verwiesen wird
@johnktejik python3 vs python2. Sie müssen basestringin py2 nachsehen.
Erikbwork
170

Python 3

In Python 3.x basestringist nicht mehr verfügbar, ebenso strwie der einzige Zeichenfolgentyp (mit der Semantik von Python 2.x unicode).

Die Prüfung in Python 3.x lautet also nur:

isinstance(obj_to_test, str)

Dies folgt dem Fix des offiziellen 2to3Konvertierungstools: Konvertieren basestringin str.

Sevenforce
quelle
94

Python 2 und 3

(kreuzkompatibel)

Wenn Sie ohne Berücksichtigung der Python-Version (2.x vs 3.x) prüfen möchten, verwenden Sie six( PyPI ) und sein string_typesAttribut:

import six

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

Innerhalb six(eines sehr leichten Einzeldateimoduls) geschieht dies einfach wie folgt :

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

if PY3:
    string_types = str
else:
    string_types = basestring
Nick T.
quelle
Alternativ können Sie future( PyPI ) verwenden, um sogar den Namen zu behalten:from past.builtins import basestring
David Nemeskey
1
Übrigens ist der Spickzettel eine großartige Ressource für die Kompatibilität der Python-Version.
David Nemeskey
1
Was ist, wenn Sie keine Importe verwenden? Versuchen Sie es zuerst basestringund greifen Sie dann auf zurück str. ZBdef is_string(obj): try: return isinstance(obj, basestring) # python 2 except NameError: return isinstance(obj, str) # python 3
isaacbernat
19

Ich fand das und mehr pythonic:

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

da Objekte vom Typ Singleton sind, wird verwendet werden , die zu vergleichen , um das Objekt zu dem str Typen zu tun

Zhou Jingyuan
quelle
4
Dies ist aufgrund der Vererbung nicht die allgemein empfohlene Methode zum Testen des Typs: Sie isinstance(obj_to_test, str)ist offensichtlich zum Testen des Typs gedacht und hat den Vorteil, dass das gleiche Verfahren wie für andere Fälle ohne Str angewendet wird.
Eric O Lebigot
14

Wenn Sie sich von expliziten Typprüfungen fernhalten möchten (und es gibt gute Gründe, sich davon fernzuhalten), ist der wahrscheinlich sicherste Teil des zu überprüfenden Zeichenfolgenprotokolls:

str(maybe_string) == maybe_string

Es wird nicht durch eine Iteration oder einen Iterator iteriert, es wird keine Liste von Zeichenfolgen als Zeichenfolge bezeichnet und es erkennt eine Zeichenfolge wie eine Zeichenfolge korrekt .

Natürlich gibt es Nachteile. Zum Beispiel str(maybe_string)kann eine schwere Berechnung sein. Wie so oft ist die Antwort, dass es darauf ankommt .

BEARBEITEN : Wie @Tcll in den Kommentaren hervorhebt , fragt die Frage tatsächlich nach einer Möglichkeit, sowohl Unicode-Zeichenfolgen als auch Bytestrings zu erkennen. In Python 2 Falseschlägt diese Antwort mit Ausnahme von Unicode-Zeichenfolgen fehl, die Nicht-ASCII-Zeichen enthalten, und in Python 3 wird sie für alle Bytestrings zurückgegeben.

klackern
quelle
Bei Objekten, die mit Darstellungsdaten initialisiert werden, funktioniert dies möglicherweise nicht wie erwartet. b = b'test'; r = str(b) == bDabei werden bdieselben Daten gespeichert wie str(b)bei (als Byte-Objekt) jedoch nicht als Zeichenfolge validiert.
Tcll
@Tcll Richtig, die Frage lautet tatsächlich "entweder normal oder Unicode". Ich glaube, ich habe es nicht richtig gelesen.
Clacke
11

Um zu überprüfen, ob Ihre Variable etwas ist, können Sie folgendermaßen vorgehen:

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

Die Ausgabe von isistance gibt Ihnen einen booleschen True- oder False-Wert, damit Sie ihn entsprechend anpassen können. Sie können das erwartete Akronym Ihres Werts überprüfen, indem Sie zunächst Folgendes verwenden: type (s) Dies gibt Ihnen den Typ 'str' zurück, damit Sie es in der isistance-Funktion verwenden können.

Abraam Georgiadis
quelle
5

Ich könnte damit im Enten-Schreibstil umgehen, wie andere erwähnen. Woher weiß ich, dass eine Zeichenfolge wirklich eine Zeichenfolge ist? Nun, offensichtlich durch Konvertieren in einen String!

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

Wenn das Argument bereits ein String- oder Unicode-Typ ist, behält real_word seinen Wert unverändert bei. Wenn das übergebene Objekt eine __unicode__Methode implementiert , wird diese verwendet, um die Unicode-Darstellung abzurufen. Wenn das übergebene Objekt nicht als Zeichenfolge verwendet werden kann, unicodelöst das integrierte Objekt eine Ausnahme aus.

SingleNegationElimination
quelle
3
isinstance(your_object, basestring)

wird wahr sein, wenn Ihr Objekt tatsächlich ein Zeichenfolgentyp ist. 'str' ist ein reserviertes Wort.

Ich entschuldige mich, die richtige Antwort ist, "basestring" anstelle von "str" ​​zu verwenden, um auch Unicode-Strings einzuschließen - wie oben von einem der anderen Responder erwähnt.

Piep Piep
quelle
Funktioniert nicht für Unicode-Objekte, die in der Frage explizit angefordert wurden.
dbn
1

Heute Abend bin ich in eine Situation geraten, in der ich dachte, ich müsste mich gegen den strTyp erkundigen, aber es stellte sich heraus, dass ich es nicht tat.

Mein Ansatz zur Lösung des Problems wird wahrscheinlich in vielen Situationen funktionieren. Daher biete ich ihn unten an, falls andere, die diese Frage lesen, interessiert sind (nur 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

Einige Tests:

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
Rick unterstützt Monica
quelle
1

Verwenden Sie einfach den folgenden Code (wir nehmen an, dass das erwähnte Objekt obj ist) -

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

Sie können es testen, indem Sie es mit einer leeren Zeichenfolge verketten:

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

Bearbeiten :

Korrektur meiner Antwort nach Kommentaren, die darauf hinweisen, dass dies bei Listen fehlschlägt

def is_string(s):
  return isinstance(s, basestring)
Georgepsarakis
quelle
Sie haben Recht, danke für den Hinweis. Ich habe eine alternative Antwort gegeben.
Georgepsarakis
-3

Für einen netten Ententypisierungsansatz für String-Likes, der den Vorteil hat, sowohl mit Python 2.x als auch mit 3.x zu arbeiten:

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

Wisefish war eng mit der Ententypisierung verbunden, bevor er zum isinstanceAnsatz überging , außer dass dies +=für Listen eine andere Bedeutung hat als dies der +Fall ist.

Alphadelta14
quelle
2
Nun, Sie haben zwei Abstimmungen und niemand hat einen Kommentar abgegeben. Ich habe nicht herabgestimmt, aber ich mag Ihre Lösung nicht, weil: * Zu ausführlich. Sie sollten dazu keine Funktion definieren müssen. * Teuer. Das Abfangen von Ausnahmen ist nicht gut für die Leistung. * Fehleranfällig. Ein anderes Objekt implementiert möglicherweise add , zeigt eine Zeichenfolge an und löst einen anderen Ausnahmetyp aus, der nicht TypeError ist.
Santiagobasulto
Auch hier wenden Sie den Ansatz der Ententypisierung an, der schön ist, aber am Ende Ausnahmen auslöst und fängt, nur um etwas herauszufinden, das nicht schön ist.
Alexey Tigarev
Dies kann zu Recht die einzige todsichere Möglichkeit sein, zwischen einer stringähnlichen und einer anderen iterierbaren Zeichenfolge zu unterscheiden. Man könnte nach Attributen suchen isalpha, aber wer weiß, nach welchen Methoden man sicher suchen kann?
Clacke
Ich erkannte, dass die __str__Methode plus Gleichheit tatsächlich die narrensichere sein kann. Aber auch das ist nicht ohne Einschränkungen.
Clacke
@ Santiagobasulto Ausnahmen sind in Python billig. Wenn Sie den Fehler 1% der Zeit erwarten, trykann schneller sein. Wenn Sie es 99% der Zeit erwarten, vielleicht nicht. Da der Leistungsunterschied minimal ist, ist es besser, idiomatisch zu sein, es sei denn, Sie profilieren Ihren Code und identifizieren ihn als tatsächlich langsam.
Nick T
-4
if type(varA) == str or type(varB) == str:
    print 'string involved'

from EDX - Online-Kurs MITx: 6.00.1x Einführung in die Informatik und Programmierung mit Python

William Clay
quelle
6
Dies ist wahrscheinlich der schlechteste Weg, dies zu überprüfen. Es schließt nicht nur Unicode-Objekte aus, sondern auch Unterklassen von str!
August