Як перевірити, чи є змінною рядок із сумісністю python 2 та 3


171

Я усвідомлюю, що можу використовувати: 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"


2
u "" Синтаксис для
лінійних ліній

Незвичайно. Я отримую `` `>>> isin substance (u" test ", basestring) True` `` на Python 2.7.16
Даракіян

Відповіді:


209

Якщо ви пишете код сумісний з 2.x і 3.x, ви, ймовірно, захочете використовувати шість :

from six import string_types
isinstance(s, string_types)

Вибачте, я трохи заплутався у наступному результаті. >>> isinstance(u"foo", string_types) True >>> isinstance(u"foo".encode("utf-8"), string_types) True Я очікував, що isin substance (u "foo", string_types) повернеться хибним.
Чандлер.Хуан

1
@ Chandler.Huang це питання щодо ідентифікації strі unicodeна Python 2, або strна Python 3. Якщо ви не хочете unicodeрозраховувати на Python 2, просто використовуйте str.
екатмур

@ecatmur заклинає, дякую! видалили його, тому ніхто не заплутався
runDOSrun

4
Ви також можете використовувати його з futureпакета замість six:from future.utils import string_types
SuperGeo

113

Найкоротший підхід, який я знайшов, не покладаючись на шість пакетів, такий:

try:
  basestring
except NameError:
  basestring = str

то, припускаючи, що ви перевіряли рядки в Python 2 найбільш загальним чином,

isinstance(s, basestring)

тепер також буде працювати для Python 3+.


10
Для py3, basestring = (str, bytes)відrequests/compat.py
Tanky Woo

Приємно, але чому? Було б добре, якби Python3 був би сумісним назад. Над рішеннями працює. Було б ще краще, якби в цьому не було потреби.
guettli

2
Щоб задовольнити підтримку py2 & 3 та mypy, я закінчивсяif not hasattr(__builtins__, "basestring"): basestring = (str, bytes)
Дейв Лі

35

Що про це, працює у всіх випадках?

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

@holdenweb: Ні і так - чудовий "хак", тільки думаю, де це потрібно ", я думаю.
Dilettant

1
Причина, чому мені подобається ця відповідь, полягає в тому, що вона миттєво переходить з python2 на 3.
Tiagojdferreira

4
Я також пішов з цим варіантом, перетворивши його на помічну функцію, тому він з’являється лише один раз, і в доктрині є місце, щоб зарахувати Філа.
Карл Сміт

2
Акуратно, і я цим самим користувався, поки не зрозумів, що я теж from __future__ import unicode_literalsактивний. Зараз я йду з:isinstance(val, (str, u"".__class__))
Грехем Клайн

18

Це відповідь @ Лева Левицького, переписана трохи.

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

The try/ exceptТест виконується один раз, а потім визначає функцію , яка завжди працює і як можна швидше.

EDIT: Насправді нам навіть не потрібно дзвонити 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(), хоча.


isinstance("", basestring)це те, що я мав на увазі під "дзвінками". У будь-якому разі +1.
Лев Левицький

1
Python - дуже динамічна мова, і я не думаю, що це взагалі погано мати тест. Це корисна техніка для того, щоб вияснити щось за один раз, і на основі цього встановити функцію, яка завжди буде правильною. Дякуємо за +1
steveha

5
Я б написав це як:try: string_types = basestring except NameError: string_types = str
jfs

12

futureБібліотека додає (в Python 2) сумісні імена , так що ви можете продовжувати писати Python 3 . Можна просто зробити наступне:

from builtins import str
isinstance(x, str) 

Щоб його встановити , просто виконайте pip install future.

Як застереження , він лише підтримує python>=2.6, >=3.3але він більш сучасний, ніж рекомендуєтьсяsix лише при використанніpython 2.5


8

Можливо, використовуйте подібне рішення

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

Вибачте за помилку, але isinstance(u'hello', basestr)приносить SyntaxError: invalid syntaxмені Python 3.2.3 під вікном 7 .. будь-яка ідея, чому це було б? Мабуть, це не подобається u- я отримую цю помилку strіbasestr
Левон

1
@Levon Немає проблем :) Це тому, що в Python3 немає такого синтаксису , як strу Python3 - це за визначенням Unicode. Відповідно, basestringтипу немає , отже NameError, це потрапило в мій фрагмент.
Лев Левицький

Зараз у нього є такий синтаксис як noop. в 3.3
Полювання на Рендалла

2
Я хотів би запропонувати , що робить try/ exceptтест один раз, і на основі результатів цього одного тесту, можна визначити isstr()правильно. Немає необхідності робити накладні винятки для кожного дзвінка isstr().
steveha

@Ranman має рацію щодо Python 3.3, ось посилання на PEP .
Лев Левицький

7

Ви можете отримати клас об'єкта, зателефонувавши object.__class__, щоб перевірити, чи є об'єкт типом рядка за замовчуванням:

    isinstance(object,"".__class__)

І Ви можете розмістити наступне у верхній частині Вашого коду, щоб рядки, укладені лапками, знаходилися в унікоді в python 2:

    from __future__ import unicode_literals

Я цього рішення зовсім небагато. Я виявив, що може бути корисно визначити str = "" .__ class__, який тепер дозволяє нормально записувати речовину (об'єкт, str), а також гарантує, що str (об'єкт) поверне рядок unicode як у Python 2, так і в Python 3.
amicitas

Це не спрацьовує при аналізі XML: some_element.textце 'str', але порівняння з 'unicode' не вдасться
сховище

Не працює з рядком unicode на python 2: isinstance (u'XXX ',' '.__ class__) == False
Fil

0

Ви можете спробувати це на початку коду:

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")

0

Будь обережний! У python 2 strі bytesпо суті однакові. Це може спричинити помилку, якщо ви намагаєтесь розрізнити їх.

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

-4

тип (рядок) == str

повертає true, якщо його рядок, а false якщо ні


1
Не вірно для Python 2, де stringє рядок unicode
lxop
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.