Как узнать, является ли объект Python строкой?

402

Как я могу проверить, является ли объект Python строкой (обычной или Unicode)?

Мэтт С.
источник
18
Джейсон имеет в виду типизацию утки (если она крякает как утка, то, вероятно, это утка). В Python вы часто «позволяете своему коду работать» на любом похожем на строку объекте, не проверяя, является ли это строка или подкласс строки. Для получения дополнительной информации см .: docs.python.org/glossary.html#term-duck-typing
Бен Хойт
4
Это то, что я люблю в SO. Я обычно задаю вопрос, но мне не отвечают, люди говорят мне, что я не должен так поступать и почему, и я расту как программист. =)
физик Майкл
24
+1: просто потому, что ответ редко требуется, не означает, что вопрос является недействительным. Хотя я думаю, что здесь очень важно проявлять осторожность, я не думаю, что это заслуживает того, чтобы опустить вопрос.
Тревор
17
Это, возможно, наиболее законное использование проверки типов в Python. Строки являются повторяемыми, поэтому отличать их от списков любым другим способом - плохая идея.
ojrac
3
Определенно есть случаи, когда необходимо отличать строки от других итераций. Например, см. Исходный код для PrettyPrinter в модуле pprint.
saxman01

Ответы:

302

Python 2

Используйте isinstance(obj, basestring)для объекта для проверки obj.

Docs .

Джон Фухи
источник
178

Python 2

Чтобы проверить, является ли объект oстроковым типом подкласса строкового типа:

isinstance(o, basestring)

потому что оба strи unicodeявляются подклассами basestring.

Чтобы проверить, является ли тип oточно str:

type(o) is str

Чтобы проверить, oявляется ли экземпляр strили любой подкласс str:

isinstance(o, str)

Вышеприведенное также работает для строк Unicode, если вы замените их strна unicode.

Тем не менее, вам может не потребоваться делать явную проверку типов вообще. «Утиная печать» может соответствовать вашим потребностям. См. Http://docs.python.org/glossary.html#term-duck-typing .

Смотрите также Что такое канонический способ проверки типа в python?

Мэтт С.
источник
локальная переменная 'str'
указана
@johnktejik python3 против python2. Вы должны проверить basestringв py2.
erikbwork
170

Python 3

В Python 3.x basestringбольше нет, так как strэто единственный тип строки (с семантикой Python 2.x unicode).

Таким образом, проверка в Python 3.x является просто:

isinstance(obj_to_test, str)

Это следует за исправлением официального 2to3инструмента конвертации: конвертация basestringв str.

sevenforce
источник
94

Python 2 и 3

(Кросс-совместимый)

Если вы хотите проверить, не обращая внимания на версию Python (2.x против 3.x), используйте six( PyPI ) и его string_typesатрибут:

import six

if isinstance(obj, six.string_types):
    print('obj is a string!')

Внутри six(очень легкий однофайловый модуль) он просто делает это :

import sys
PY3 = sys.version_info[0] == 3

if PY3:
    string_types = str
else:
    string_types = basestring
Ник Т
источник
Кроме того, вы можете использовать future( PyPI ), чтобы даже сохранить имя:from past.builtins import basestring
Дэвид Nemeskey
1
Кстати, Шпаргалка - отличный ресурс для совместимости версий Python.
Дэвид Немески
1
Как насчет не использовать импорт? Сначала попробуйте, basestringа затем вернитесь к str. Напримерdef is_string(obj): try: return isinstance(obj, basestring) # python 2 except NameError: return isinstance(obj, str) # python 3
isaacbernat
19

Я нашел это и многое другое pythonic:

if type(aObject) is str:
    #do your stuff here
    pass

поскольку объекты типа являются синглтоном, это может использоваться , чтобы сделать сравнение объекта с типом ули

Чжоу Цзиньюань
источник
4
Это не общий рекомендуемый способ проверки на тип из-за наследования: isinstance(obj_to_test, str)очевидно, он предназначен для проверки на тип и имеет преимущество в использовании той же процедуры, что и в других, не относящихся к делу случаях.
Эрик О Лебиго
14

Если кто-то хочет избежать явной проверки типов (и для этого есть веские причины), возможно, самая безопасная часть строкового протокола для проверки:

str(maybe_string) == maybe_string

Это не итерация через итератор или итератор, он не будет вызывать список-оф-строки в строку , и это правильно обнаруживает струноподобный в виде строки.

Конечно, есть и недостатки. Например, str(maybe_string)может быть тяжелый расчет. Как часто, ответ - это зависит .

РЕДАКТИРОВАТЬ: Как @Tcll указывает в комментариях, вопрос на самом деле просит способ обнаружить как строки Unicode, так и строки байтов. В Python 2 этот ответ не удастся, за исключением строк Unicode, которые содержат символы не ASCII, а в Python 3 он вернется Falseдля всех строк байтов.

clacke
источник
В случае объектов, которые инициализируются с данными представления, это может работать не так, как ожидалось ... b = b'test'; r = str(b) == bгде bхранятся те же данные, что и, str(b)но (будучи объектом байтов) не проверяется как строка.
Tcll
@Tcll Правильно, вопрос на самом деле говорит "обычный или Unicode". Я думаю, что я не прочитал это правильно.
клик
11

Чтобы проверить, является ли ваша переменная чем-то похожим:

s='Hello World'
if isinstance(s,str):
#do something here,

Вывод isistance выдаст вам логическое значение True или False, чтобы вы могли соответственно отрегулировать. Вы можете проверить ожидаемую аббревиатуру вашего значения, первоначально используя: type (s). Это вернет вам тип 'str', чтобы вы могли использовать его в функции isistance.

Абраам Георгиадис
источник
5

Я мог бы иметь дело с этим в стиле печати утки, как другие упоминают. Как я узнаю, что строка действительно является строкой? ну, очевидно, преобразовав его в строку!

def myfunc(word):
    word = unicode(word)
    ...

Если arg уже является строковым или юникодным типом, real_word будет хранить его значение без изменений. Если переданный объект реализует __unicode__метод, который используется для получения его представления в юникоде. Если переданный объект не может использоваться как строка, unicodeвстроенная функция вызывает исключение.

SingleNegationElimination
источник
3
isinstance(your_object, basestring)

будет True, если ваш объект действительно является строковым типом. «str» - зарезервированное слово

мои извинения, правильный ответ использует 'basestring' вместо 'str' для того, чтобы он также включал строки Unicode - как было отмечено выше одним из других респондентов.

beepbeep
источник
Не работает с объектами Unicode, которые были явно запрошены в вопросе.
д.б.н.
1

Этим вечером я столкнулся с ситуацией, в которой я думал, что должен будет проверить strтип, но оказалось, что я не сделал.

Мой подход к решению проблемы, вероятно, будет работать во многих ситуациях, поэтому я предлагаю его ниже на тот случай, если другие, читающие этот вопрос, будут заинтересованы (только Python 3).

# NOTE: fields is an object that COULD be any number of things, including:
# - a single string-like object
# - a string-like object that needs to be converted to a sequence of 
# string-like objects at some separator, sep
# - a sequence of string-like objects
def getfields(*fields, sep=' ', validator=lambda f: True):
    '''Take a field sequence definition and yield from a validated
     field sequence. Accepts a string, a string with separators, 
     or a sequence of strings'''
    if fields:
        try:
            # single unpack in the case of a single argument
            fieldseq, = fields
            try:
                # convert to string sequence if string
                fieldseq = fieldseq.split(sep)
            except AttributeError:
                # not a string; assume other iterable
                pass
        except ValueError:
            # not a single argument and not a string
            fieldseq = fields
        invalid_fields = [field for field in fieldseq if not validator(field)]
        if invalid_fields:
            raise ValueError('One or more field names is invalid:\n'
                             '{!r}'.format(invalid_fields))
    else:
        raise ValueError('No fields were provided')
    try:
        yield from fieldseq
    except TypeError as e:
        raise ValueError('Single field argument must be a string'
                         'or an interable') from e

Некоторые тесты:

from . import getfields

def test_getfields_novalidation():
    result = ['a', 'b']
    assert list(getfields('a b')) == result
    assert list(getfields('a,b', sep=',')) == result
    assert list(getfields('a', 'b')) == result
    assert list(getfields(['a', 'b'])) == result
Рик поддерживает Монику
источник
1

Это просто, используйте следующий код (мы предполагаем, что упомянутый объект является obj) -

if type(obj) == str:
    print('It is a string')
else:
    print('It is not a string.')
Abhijeet.py
источник
0

Вы можете проверить это путем объединения с пустой строкой:

def is_string(s):
  try:
    s += ''
  except:
    return False
  return True

Редактировать :

Исправление моего ответа после комментариев, указывающих, что это не удается со списками

def is_string(s):
  return isinstance(s, basestring)
georgepsarakis
источник
Вы правы, спасибо за указание. Я дал альтернативный ответ.
Георгепсаракис
-3

Для хорошего подхода к типизации уток для подобных строк, у которого есть бонус работы с Python 2.x и 3.x:

def is_string(obj):
    try:
        obj + ''
        return True
    except TypeError:
        return False

Wisefish был близок к тому, чтобы печатать на утке, прежде чем он переключился на isinstanceподход, за исключением того, что он +=имеет другое значение для списков, чем +делает.

Alphadelta14
источник
2
Ну, у вас есть два отрицательных отзыва, и никто не предоставил комментарий. Я не отрицал, но мне не нравится ваше решение, потому что: * Слишком многословно. Вам не нужно определять функцию для этого. * Дорогой. Поймать исключения не хорошо для производительности. * Ошибка склонна. Другой объект может реализовать add , увидеть строку и вызвать другой тип исключения, который не является TypeError.
santiagobasulto
Также здесь вы применяете подход «типизирование утки», который прекрасен, но в конечном итоге выдает исключение и бросает только для того, чтобы найти что-то, что не красиво.
Алексей Тигарев
Это может быть законно единственный верный способ различить строковый и некоторые другие повторяемые строки. Можно искать такие атрибуты, как isalpha, но кто знает, какие методы было бы безопасно искать?
глэк
Я понял, что __str__метод плюс равенство на самом деле может быть надежным. Но даже это не без предостережений.
Clacke
Исключения @santiagobasulto дешевы в Python. Если вы ожидаете ошибку 1% времени, tryможет быть быстрее. Если вы ожидаете это в 99% случаев, возможно, нет. Разница в производительности минимальна, лучше быть идиоматичным, если вы не профилируете свой код и не определите, что он действительно медленный.
Ник Т
-4
if type(varA) == str or type(varB) == str:
    print 'string involved'

от EDX - онлайн курс MITx: 6.00.1x Введение в информатику и программирование с использованием Python

Уильям Клэй
источник
6
Это, наверное, худший из возможных способов проверки. Он не только исключает объекты Unicode, но даже исключает подклассы str!
Авгурар