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

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


person Matt S.    schedule 19.08.2009    source источник
comment
То, что имеет в виду Джейсон, - это утиная печать (если она крякает, как утка, вероятно, это утка). В Python вы часто позволяете своему коду работать с любым строковым объектом, не проверяя, является ли он строковым или строковым подклассом. Для получения дополнительной информации см .: docs.python.org/glossary.html#term- утиная печать   -  person Ben Hoyt    schedule 20.08.2009
comment
Это то, что мне нравится в SO. Я обычно задаю вопрос, но мне не отвечают, люди говорят мне, что я все равно не должен этого делать и почему, и я расту как программист. знак равно   -  person physicsmichael    schedule 20.08.2009
comment
+1: Тот факт, что ответ нужен редко, не означает, что вопрос недействителен. Хотя я думаю, что здесь есть предостережение, я не думаю, что это заслуживает понижения вопроса.   -  person Trevor    schedule 09.03.2013
comment
Возможно, это наиболее законное использование проверки типов в Python. Строки можно повторять, поэтому отличать их от списков любым другим способом - плохая идея.   -  person ojrac    schedule 15.03.2013
comment
Определенно есть случаи, когда необходимо отличать строки от других итераций. Например, см. Исходный код PrettyPrinter в модуле pprint.   -  person saxman01    schedule 10.06.2014
comment
«Если он похож на утку и крякает, как утка, значит, это утка».   -  person R__raki__    schedule 19.01.2016
comment
Я думаю, что утиная печать предназначена для работы с полиморфизмом. Некоторые люди резко сопротивляются ВСЕЙ проверке типов на Python. Ссылка Бена на самом деле не говорит против вещей, в которых типы принципиально различное поведение. Я считаю, что утиная печать предназначена для доверия Принципу замены Лискова   -  person John Walthour    schedule 07.05.2016
comment
Строки - это не только итерации, но и итерации строк. Отличить их от других итераций строки без «обмана» практически невозможно. Но есть stringlike, и чит-код ломается.   -  person clacke    schedule 28.07.2016
comment
Поскольку многие новые люди, вероятно, прочитают это: сначала убедитесь, что вам действительно нужно проверить. Мой ответ может дать некоторые идеи о том, как избежать проверки.   -  person Rick supports Monica    schedule 21.07.2017
comment
Также см. stackoverflow.com/questions/4843173/   -  person crizCraig    schedule 10.07.2018
comment
Я не могу поверить, что на этот вопрос нет принятого ответа   -  person hyankov    schedule 19.01.2020


Ответы (14)


Python 2

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

Документы.

person John Fouhy    schedule 19.08.2009

Python 3

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

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

isinstance(obj_to_test, str)

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

person sevenforce    schedule 23.10.2014
comment
Это не работает для строковых объектов: isinstance (collections.UserString (foe), str) == False - person loutre; 22.12.2020
comment
@loutre Спасибо за ваш комментарий. С пользовательскими коллекциями (UserString, UserDict, UserList) я раньше не сталкивался. Эти типы уже предшествовали Python 2. Поскольку эти типы не наследуются от встроенных типов str, dict или list, вызов isinstance не будет работать. К вашему сведению: из-за этого не гарантируется, что эти типы могут использоваться в качестве замены. Например. модуль регулярных выражений re не работает с UserString (по крайней мере, с Python 3.8.2). - person sevenforce; 23.12.2020

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 ?

person Matt S.    schedule 19.08.2009
comment
локальная переменная 'str', на которую ссылается перед присваиванием - person john ktejik; 30.10.2017
comment
@johnktejik python3 против python2. Вам нужно проверить basestring в py2. - person erikbwork; 29.08.2018

Python 2 и 3

(перекрестная совместимость)

Если вы хотите проверить без учета версии Python (2.x против 3.x), используйте _1 _ (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
person Nick T    schedule 16.05.2014
comment
В качестве альтернативы вы можете использовать future (PyPI), чтобы даже сохранить имя: from past.builtins import basestring - person David Nemeskey; 08.02.2017
comment
Кстати, Cheat Sheet - отличный ресурс для совместимости версий Python. - person David Nemeskey; 08.02.2017
comment
А как насчет того, чтобы не использовать импорт? Сначала попробуйте basestring, а затем вернитесь к str. Например. def is_string(obj): try: return isinstance(obj, basestring) # python 2 except NameError: return isinstance(obj, str) # python 3 - person isaacbernat; 13.08.2017

Я нашел это и еще pythonic:

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

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

person Zhou Jingyuan    schedule 14.06.2016
comment
Это не общий рекомендуемый способ проверки типа из-за наследования: isinstance(obj_to_test, str), очевидно, предназначен для проверки типа, и его преимущество заключается в использовании той же процедуры, что и для других случаев, отличных от str. - person Eric O Lebigot; 17.06.2018

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

str(maybe_string) == maybe_string

Он не будет выполнять итерацию через итератор или итератор, он не будет называть список строк строкой и правильно обнаруживает stringlike в виде строки.

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

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

person clacke    schedule 28.07.2016
comment
В случае объектов, которые инициализируются данными представления, это может работать не так, как ожидалось ... b = b'test'; r = str(b) == b где b содержит те же данные, что и str(b), но (будучи объектом байтов) не проверяется как строка. - person Tcll; 06.12.2019
comment
@Tcll Верно, вопрос на самом деле говорит либо обычный, либо Unicode. Думаю, я не прочитал это как следует. - person clacke; 05.01.2020

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

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

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

person Abraam Georgiadis    schedule 30.06.2016

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

if type(obj) == str:
    print('It is a string')
else:
    print('It is not a string.')
person Abhijeet.py    schedule 31.03.2020

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

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

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

person SingleNegationElimination    schedule 21.08.2009

isinstance(your_object, basestring)

будет True, если ваш объект действительно строкового типа. 'str' - зарезервированное слово.

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

person beepbeep    schedule 19.03.2014
comment
Не работает для объектов Unicode, которые были явно запрошены в вопросе. - person dbn; 02.05.2014

Этим вечером я столкнулся с ситуацией, когда думал, что мне нужно будет проверить тип 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
person Rick supports Monica    schedule 21.07.2017

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

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

Изменить:

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

def is_string(s):
  return isinstance(s, basestring)
person georgepsarakis    schedule 24.01.2013

if type(varA) == str or type(varB) == str:
    print 'string involved'

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

person William Clay    schedule 11.09.2014
comment
Вероятно, это наихудший способ проверки. Он не только исключает объекты Unicode, но даже исключает подклассы str! - person augurar; 17.12.2014

Для хорошего подхода к утиной печати для строковых символов, который дает бонус работы как с Python 2.x, так и с 3.x:

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

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

person Alphadelta14    schedule 16.11.2014
comment
Что ж, у вас два отрицательных голоса, и никто не прокомментировал. Я не голосовал против, но мне не нравится ваше решение, потому что: * Слишком многословно. Для этого не нужно определять функцию. * Дорогие. Перехват исключений плохо сказывается на производительности. * Склонность к ошибкам. Другой объект может реализовать add, увидеть строку и вызвать другой тип исключения, а не TypeError. - person santiagobasulto; 03.12.2015
comment
Также здесь вы используете подход «утиная типизация», который прекрасен, но в конечном итоге выдает и перехватывает исключение только для того, чтобы узнать что-то, что некрасиво. - person Alexey Tigarev; 05.01.2016
comment
Это может быть законно единственным верным способом отличить строку, подобную строке, от другой итерации строки. Можно было бы искать атрибуты типа isalpha, но кто знает, какие методы было бы безопасно искать? - person clacke; 28.07.2016
comment
Я понял, что метод __str__ плюс равенство на самом деле может быть надежным. Но даже это не без оговорок. - person clacke; 28.07.2016
comment
Исключения @santiagobasulto дешевы в Python. Если вы ожидаете ошибки в 1% случаев, try может быть быстрее. Если вы ожидаете этого в 99% случаев, возможно, нет. Разница в производительности минимальна, поэтому лучше вести себя идиоматично, если вы не профилируете свой код и не идентифицируете его как действительно медленный. - person Nick T; 08.02.2017