Как да проверите дали променливата е низ със съвместимост на python 2 и 3

Наясно съм, че мога да използвам: isinstance(x, str) в python-3.x, но трябва да проверя дали нещо е низ и в python-2.x. Ще работи ли isinstance(x, str) както се очаква в python-2.x? Или ще трябва да проверя версията и да използвам isinstance(x, basestr)?

По-конкретно, в python-2.x:

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

и python-3.x няма u"foo"


person Randall Hunt    schedule 02.07.2012    source източник
comment
u синтаксисът за Unicode литералите е въведен отново в Python 3.3   -  person jfs    schedule 03.07.2012
comment
Странно. Получавам ``` ››› isinstance(utest, basestring) True ``` на Python 2.7.16   -  person Darakian    schedule 14.05.2019


Отговори (10)


Ако пишете 2.x-and-3.x-съвместим код, вероятно ще искате да използвате шест:

from six import string_types
isinstance(s, string_types)
person ecatmur    schedule 02.07.2012
comment
Съжалявам, че съм малко объркан относно следния резултат. >>> isinstance(u"foo", string_types) True >>> isinstance(u"foo".encode("utf-8"), string_types) True Очаквах isinstance(ufoo, string_types) да върне невярно. - person Chandler.Huang; 31.03.2016
comment
@Chandler.Huang, този въпрос е относно идентифицирането на str и unicode на Python 2 или str на Python 3. Ако не искате unicode да разчита на Python 2, просто използвайте str. - person ecatmur; 31.03.2016
comment
@ecatmur уау, благодаря! го изтри, така че никой да не се обърка - person runDOSrun; 29.09.2017
comment
можете също да го използвате от future пакет вместо six: from future.utils import string_types - person SuperGeo; 24.06.2018

Най-краткият подход, който открих, без да разчитам на пакети като шест, е:

try:
  basestring
except NameError:
  basestring = str

тогава, ако приемем, че сте проверявали за низове в Python 2 по най-общия начин,

isinstance(s, basestring)

вече ще работи и за Python 3+.

person hbristow    schedule 27.03.2014
comment
За py3, basestring = (str, bytes) от requests/compat.py - person Tanky Woo; 17.01.2016
comment
Хубаво, но защо? Би било хубаво Python3 да бъде обратно съвместим тук. Горните решения работят. Би било още по-добре, ако нямаше нужда от това. - person guettli; 04.03.2019
comment
За да задоволя както поддръжката на py2 &3, така и mypy, завърших с if not hasattr(__builtins__, "basestring"): basestring = (str, bytes) - person Dave Lee; 11.04.2019

Какво ще кажете за това, работи във всички случаи?

isinstance(x, ("".__class__, u"".__class__))
person Fil    schedule 13.11.2015
comment
@holdenweb: Не и да - мисля, че изящният хак въздейства само там, където е необходимо. - person Dilettant; 31.03.2017
comment
Причината, поради която харесвам този отговор, е, че е приятелски настроен към мигрирането от python2 към 3. - person Tiagojdferreira; 18.01.2018
comment
Аз също използвах тази опция, като я опаковах в помощна функция, така че да се появява само веднъж и има място в документалния низ за приписване на Fil. - person Carl Smith; 21.05.2018
comment
Добре, и аз самият го използвах, докато разбрах, че също имам from __future__ import unicode_literals активен. Сега отивам с: isinstance(val, (str, u"".__class__)) - person Graham Klyne; 23.08.2018

Това е отговорът на @Lev Levitsky, пренаписан малко.

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

Тестът try/except се прави веднъж и след това дефинира функция, която винаги работи и е възможно най-бърза.

РЕДАКТИРАНЕ: Всъщност дори не е нужно да извикваме isinstance(); просто трябва да оценим basestring и да видим дали ще получим NameError:

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

Мисля обаче, че е по-лесно да се следва с обаждането до isinstance().

person steveha    schedule 02.07.2012
comment
isinstance("", basestring) е това, което имах предвид с обаждането. Както и да е, +1. - person Lev Levitsky; 03.07.2012
comment
Python е много динамичен език и не мисля, че изобщо изглежда зле да има такъв тест. Това е полезна техника за измисляне на нещо еднократно и въз основа на това настройка на функция, която винаги ще бъде правилна. Благодаря за +1. - person steveha; 03.07.2012
comment
Бих го написал като: try: string_types = basestring except NameError: string_types = str - person jfs; 04.07.2012

future библиотека добавя (към Python 2) съвместими имена, така че можете да продължите да пишете Python 3. Можете просто да направите следното:

from builtins import str
isinstance(x, str) 

За да го инсталирате, просто изпълнете pip install future.

Като предупреждение, той поддържа само python>=2.6,>=3.3, но е по-модерен от six, който е само препоръчително, ако използвате python 2.5

person toto_tico    schedule 09.10.2017
comment
from builtins import str; isinstance('foo', str) връща False в python 2.7 - person Emre; 11.02.2021

Може би използвайте заобиколно решение като

def isstr(s):
    try:
        return isinstance(s, basestring)
    except NameError:
        return isinstance(s, str)
person Lev Levitsky    schedule 02.07.2012
comment
Съжалявам, че ви притеснявам, но isinstance(u'hello', basestr) дава SyntaxError: invalid syntax за мен с Python 3.2.3 под Window 7 .. някаква идея защо би било това? Изглежда не харесва u - получавам тази грешка с str и basestr - person Levon; 03.07.2012
comment
@Levon Няма проблем :) Това е защото Python3 няма този синтаксис, тъй като str в Python3 по дефиниция е Unicode. Съответно, няма тип basestring, следователно NameError, който е уловен в моя фрагмент. - person Lev Levitsky; 03.07.2012
comment
Сега има този синтаксис като noop. в 3.3 - person Randall Hunt; 03.07.2012
comment
Бих предложил да направите теста try/except един път и въз основа на резултатите от този единичен тест да дефинирате правилно isstr(). Няма нужда да се налагат допълнителни разходи за изключение за всяко повикване към isstr(). - person steveha; 03.07.2012
comment
@Ranman е прав за Python 3.3, ето връзка към PEP. - person Lev Levitsky; 03.07.2012
comment
@steveha Добра гледна точка, но това би изглеждало някак зле, тъй като човек трябва действително да извика функцията веднъж, за да бъде повдигнато изключението. - person Lev Levitsky; 03.07.2012
comment
@LevLevitsky, не е необходимо да извиквате функцията, за да тествате кой начин да дефинирате функцията. Добре, ще публикувам това като отговор, тъй като кодът изглежда зле в коментар. - person steveha; 03.07.2012
comment
Левон каза, че е повдигнала синтактична грешка, а не NameError. Прави това, защото е basestring, а не basestr - person Tatarize; 17.07.2019

Можете да получите класа на обект, като извикате object.__class__, така че, за да проверите дали обектът е тип низ по подразбиране:

    isinstance(object,"".__class__)

И можете да поставите следното в горната част на вашия код, така че низовете, оградени с кавички, да са в unicode в python 2:

    from __future__ import unicode_literals
person Martin Hansen    schedule 28.02.2013
comment
Аз това решение доста. Открих, че може да бъде полезно да дефинирам str = .__class__, което сега позволява isinstance(object, str) да бъде написан нормално и също така гарантира, че str(object) ще върне уникод низ както в Python 2, така и в Python 3. - person amicitas; 05.12.2013
comment
Това не работи при анализиране на XML: some_element.text е „str“, но сравнението с „unicode“ ще бъде неуспешно - person vault; 24.07.2015
comment
Не работи с unicode низ на python 2: isinstance(u'XXX', ''.__class__) == False - person Fil; 13.11.2015

Можете да опитате това в началото на вашия код:

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

и по-късно в кода:

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

Бъди внимателен! В python 2 str и bytes по същество са едни и същи. Това може да причини грешка, ако се опитвате да разграничите двете.

>>> size = 5    
>>> byte_arr = bytes(size)
>>> isinstance(byte_arr, bytes)
True
>>> isinstance(byte_arr, str)
True
person Fardin Abdi    schedule 07.10.2019

тип (низ) == str

връща true, ако е низ, и false, ако не е

person confused_programmer241    schedule 08.06.2016
comment
Не е вярно за Python 2, където string е уникод низ - person lxop; 05.08.2016