So überprüfen Sie, ob die Variable eine Zeichenfolge mit Python 2- und 3-Kompatibilität ist


171

Ich bin mir bewusst, dass ich Folgendes verwenden kann: isinstance(x, str)in Python-3.x, aber ich muss auch überprüfen, ob etwas in Python-2.x eine Zeichenfolge ist. Funktioniert es isinstance(x, str)wie erwartet in Python-2.x? Oder muss ich die Version überprüfen und verwenden isinstance(x, basestr)?

Insbesondere in Python-2.x:

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

und Python-3.x hat nicht u"foo"


2
Die Syntax für Unicode-Literale wird in Python 3.3
jfs

Seltsam. Ich bekomme `` `>>> isinstance (u" test ", basestring) True` `` auf Python 2.7.16
Darakian

Antworten:


209

Wenn Sie 2.x- und 3.x-kompatiblen Code schreiben, möchten Sie wahrscheinlich sechs verwenden :

from six import string_types
isinstance(s, string_types)

Entschuldigung, ich bin etwas verwirrt über das folgende Ergebnis. >>> isinstance(u"foo", string_types) True >>> isinstance(u"foo".encode("utf-8"), string_types) True Ich hatte erwartet, dass isinstance (u "foo", string_types) false zurückgibt.
Chandler.Huang

1
Diese Frage @ Chandler.Huang ist zu identifizieren strund unicodeauf Python 2 oder strauf Python 3. Wenn Sie nicht wollen , unicodeauf Python 2 zählen, nur verwenden str.
Ecatmur

@ecatmur woops, danke! löschte es, so dass niemand verwirrt wird
runDOSrun

4
Sie können es auch aus dem futurePaket verwenden, anstatt six:from future.utils import string_types
SuperGeo

113

Der knappste Ansatz, den ich gefunden habe, ohne mich auf Pakete wie sechs zu verlassen, ist:

try:
  basestring
except NameError:
  basestring = str

Angenommen, Sie haben in Python 2 auf die allgemeinste Weise nach Zeichenfolgen gesucht.

isinstance(s, basestring)

funktioniert jetzt auch für Python 3+.


10
Für py3, basestring = (str, bytes)vonrequests/compat.py
Tanky Woo

Schön, aber warum? Es wäre schön, wenn Python3 hier abwärtskompatibel wäre. Die oben genannten Lösungen funktionieren. Wäre noch besser, wenn es nicht nötig wäre.
Guettli

2
Um sowohl die py2 & 3 Unterstützung als auch mypy zu befriedigen, endete ich mitif not hasattr(__builtins__, "basestring"): basestring = (str, bytes)
Dave Lee

35

Was ist damit, funktioniert in allen Fällen?

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

@holdenweb: Nein und ja - ein geschickter Hack "denke nur, wo es nötig ist", denke ich.
Dilettant

1
Der Grund, warum ich diese Antwort mag, ist, dass sie mit der Migration von Python2 auf 3 freundlich ist.
Tiagojdferreira

4
Ich habe mich auch für diese Option entschieden und sie in eine Hilfsfunktion eingebunden, sodass sie nur einmal angezeigt wird und in der Dokumentzeichenfolge ein Platz für die Gutschrift von Fil vorhanden ist.
Carl Smith

2
Ordentlich, und ich habe es selbst benutzt, bis mir klar wurde, dass ich auch from __future__ import unicode_literalsaktiv bin . Jetzt gehe ich mit:isinstance(val, (str, u"".__class__))
Graham Klyne

18

Dies ist die Antwort von @Lev Levitsky, die ein wenig umgeschrieben wurde.

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

Der try/ excepttest wird einmal durchgeführt und definiert dann eine Funktion, die immer funktioniert und so schnell wie möglich ist.

EDIT: Eigentlich müssen wir nicht einmal anrufen isinstance(); wir müssen nur bewerten basestringund sehen, ob wir eine bekommen NameError:

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

Ich denke, es ist jedoch einfacher, dem Anruf zu folgen isinstance().


isinstance("", basestring)ist das, was ich mit "anrufen" gemeint habe. Wie auch immer, +1.
Lev Levitsky

1
Python ist eine sehr dynamische Sprache, und ich denke, es sieht überhaupt nicht schlecht aus, einen solchen Test zu haben. Dies ist eine nützliche Technik, um einmal etwas herauszufinden und darauf basierend eine Funktion einzurichten, die immer korrekt ist. Danke für die +1.
Steveha

5
Ich würde es schreiben als:try: string_types = basestring except NameError: string_types = str
jfs

12

Die futureBibliothek fügt (zu Python 2) kompatible Namen hinzu , sodass Sie Python 3 weiter schreiben können . Sie können einfach Folgendes tun:

from builtins import str
isinstance(x, str) 

Um es zu installieren , führen Sie es einfach aus pip install future.

Als Einschränkung , unterstützt es nur python>=2.6, >=3.3aber es ist moderner als six, die nur bei Verwendung empfohlenpython 2.5


8

Verwenden Sie möglicherweise eine Problemumgehung wie

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

Leider abzuhören Sie aber die isinstance(u'hello', basestr)Renditen SyntaxError: invalid syntaxfür mich mit Python 3.2.3 unter Windows 7 .. eine Idee , warum dies wäre? Es scheint nicht zu gefallen u- ich bekomme diesen Fehler mit strundbasestr
Levon

1
@Levon Kein Problem :) Das liegt daran, dass Python3 diese Syntax nicht hat , da strPython3 per Definition Unicode ist. Dementsprechend gibt es keinen basestringTyp, daher der NameError, der in meinem Snippet gefangen ist.
Lev Levitsky

Es hat diese Syntax jetzt als Noop. in 3.3
Randall Hunt

2
Ich würde vorschlagen, den try/ excepttest ein einziges Mal durchzuführen, und basierend auf den Ergebnissen dieses einzelnen Tests definieren Sie ihn isstr()korrekt. Es ist nicht erforderlich, bei jedem Aufruf von den Overhead einer Ausnahme zu verursachen isstr().
Steveha

@Ranman hat Recht mit Python 3.3, hier ist ein Link zum PEP .
Lev Levitsky

7

Sie können die Klasse eines Objekts durch Aufrufen abrufen object.__class__, um zu überprüfen, ob das Objekt der Standardzeichenfolgentyp ist:

    isinstance(object,"".__class__)

Und Sie können Folgendes oben in Ihren Code einfügen, sodass in Anführungszeichen eingeschlossene Zeichenfolgen in Python 2 in Unicode sind:

    from __future__ import unicode_literals

Ich diese Lösung ziemlich viel. Ich fand es nützlich, str = "" .__ class__ zu definieren, wodurch nun isinstance (object, str) normal geschrieben werden kann und sichergestellt wird, dass str (object) sowohl in Python 2 als auch in Python 3 eine Unicode-Zeichenfolge zurückgibt.
Amicitas

Dies funktioniert nicht beim Parsen von XML: some_element.textist ein 'str', aber der Vergleich mit 'unicode' würde fehlschlagen
Tresor

Funktioniert nicht mit Unicode-Zeichenfolgen unter Python 2: isinstance (u'XXX ',' '.__ class__) == False
Fil

0

Sie können dies am Anfang Ihres Codes versuchen:

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

und später im Code:

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

0

Achtung! In Python 2 strund bytessind im Wesentlichen gleich. Dies kann einen Fehler verursachen, wenn Sie versuchen, zwischen den beiden zu unterscheiden.

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

-4

Typ (Zeichenfolge) == Str

Gibt true zurück, wenn es sich um eine Zeichenfolge handelt, und false, wenn nicht


1
Nicht wahr für Python 2, wo stringeine Unicode-Zeichenfolge ist
lxop
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.