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"

Randall Hunt
quelle
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)
ecatmur
quelle
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+.

hbristow
quelle
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__))
Fil
quelle
@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().

steveha
quelle
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

toto_tico
quelle
8

Verwenden Sie möglicherweise eine Problemumgehung wie

def isstr(s):
    try:
        return isinstance(s, basestring)
    except NameError:
        return isinstance(s, str)
Lev Levitsky
quelle
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
Martin Hansen
quelle
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")
Bunkus
quelle
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
Fardin
quelle
-4

Typ (Zeichenfolge) == Str

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

confused_programmer241
quelle
1
Nicht wahr für Python 2, wo stringeine Unicode-Zeichenfolge ist
lxop