Как проверить, является ли переменная строкой с совместимостью с 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 и 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) вернет false. - 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 woops, спасибо! удалил его, чтобы никто не запутался - 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
Я также выбрал эту опцию, заключив ее во вспомогательную функцию, чтобы она появлялась только один раз, а в строке документации есть место, где можно указать Фил. - person Carl Smith; 21.05.2018
comment
Аккуратно, и я сам им пользовался, пока не понял, что у меня тоже from __future__ import unicode_literals active. Теперь я использую: 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)

Тест _2 _ / _ 3_ выполняется один раз, а затем определяет функцию, которая всегда работает и работает максимально быстро.

РЕДАКТИРОВАТЬ: На самом деле нам даже не нужно вызывать 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.

В качестве предостережения, он поддерживает только _4 _, _ 5_, но он более современный, чем 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
Я бы посоветовал провести _1 _ / _ 2_ тест один раз, и, основываясь на результатах этого единственного теста, вы правильно определите 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__)

И вы можете разместить следующее в верхней части вашего кода, чтобы строки, заключенные в кавычки, были в юникоде в python 2:

    from __future__ import unicode_literals
person Martin Hansen    schedule 28.02.2013
comment
Мне этого решения совсем немного. Я обнаружил, что может быть полезно определить str = .__ class__, который теперь позволяет нормально записывать isinstance (object, str), а также гарантирует, что str (object) вернет строку Unicode как в 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

возвращает истину, если это строка, и ложь, если нет

person confused_programmer241    schedule 08.06.2016
comment
Не верно для Python 2, где string - строка в Юникоде. - person lxop; 05.08.2016