Як дізнатися, чи об’єкт Python є рядком?


402

Як я можу перевірити, чи об'єктом Python є рядок (звичайний чи Unicode)?


18
Те, що має на увазі Джейсон, - це натискання качок (якщо воно качкає, як качка, ймовірно, це качка). У Python ви часто "дозволяєте вашому коду працювати" на будь-якому рядковому об'єкті, не перевіряючи, чи це підрядний рядок або рядок. Для отримання додаткової інформації дивіться: docs.python.org/glossary.html#term-duck-typing
Бен Хойт

4
Це те, що я люблю в SO. Зазвичай я задаю питання, на нього не відповідають, люди мені кажуть, що я не повинен цього робити і чому, і я роблю програмістом. =)
physicsmichael

24
+1: Тільки тому, що відповідь рідко потрібна, не означає, що питання є недійсним. Хоча, я думаю, що це здорово, щоб бути обережними тут, я не думаю, що це заслуговує на те, щоб зняти питання.
Тревор

17
Це, можливо, найбільш легітимне використання перевірки типу в Python. Рядки є ітерабельними, тому відрізняти їх від списків будь-яким іншим способом - погана ідея.
ojrac

3
Однозначно є випадки, коли потрібно відрізняти рядки від інших ітерабелів. Наприклад, дивіться вихідний код для PrettyPrinter в модулі pprint.
saxman01

Відповіді:



178

Пітон 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', на яку посилався перед призначенням,
John ktejik

@johnktejik python3 vs python2. Вам потрібно перевірити basestringв py2.
erikbwork

170

Пітон 3

У Python 3.x basestringбільше не доступний, як strі єдиний тип рядка (із семантикою Python 2.x's unicode).

Тож перевірка в Python 3.x просто:

isinstance(obj_to_test, str)

З цього випливає виправлення офіційного 2to3інструменту перетворення: перетворення basestringв str.


94

Пітон 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
David Nemeskey

1
BTW Cheat Sheet - це чудовий ресурс сумісності версій 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)може бути важкий розрахунок. Як це часто, відповідь - це залежить .

EDIT: Як в коментарях вказує @Tcll , питання насправді вимагає способу виявлення як рядків unicode, так і bytestrings. На Python 2 ця відповідь буде невдалою, за винятком рядків Unicode, що містять символи, що не належать до ASCII, а на Python 3 повернеться Falseдля всіх байтов.


У випадку об'єктів, які ініціалізуються з даними представлення, це може не працювати, як очікувалося ... b = b'test'; r = str(b) == bтам, де bзберігаються ті самі дані, що і, str(b)але (будучи об'єктом байтів), не перевіряється як рядок.
Tcll

@Tcll Правильно, питання насправді говорить "або регулярно, або Unicode". Я думаю, я не прочитав це належним чином.
клаке

11

Для того, щоб перевірити, чи є ваша змінна чимось:

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

Вихід опору дасть вам булеве значення True або False, щоб ви могли відповідно налаштувати. Ви можете перевірити очікувану абревіатуру вашої величини, спочатку скориставшись: type (s) Це поверне вам тип "str", щоб ви могли використовувати його у функції isistance.


5

Я можу мати справу з цим у стилі набору качки, як і інші згадки. Як дізнатись, що струна - це дійсно рядок? ну, очевидно, перетворивши його на рядок!

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

Якщо аргумент - це вже рядок або тип унікоду, real_word утримуватиме його значення без змін. Якщо переданий об'єкт реалізує __unicode__метод, який використовується для отримання його уявлення унікоду. Якщо переданий об'єкт не може бути використаний як рядок, unicodeвбудований створює виняток.


3
isinstance(your_object, basestring)

буде правдою, якщо ваш об’єкт справді є рядковим. 'str' - це зарезервоване слово.

мої вибачення, правильна відповідь використовує 'basestring' замість 'str' для того, щоб він також включав рядки unicode, - як вище зазначав один з інших респондентів.


Не працює для об’єктів unicode, про які було чітко запитано у запитанні.
dbn

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.')

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

мудрі рибки були близькими з типом качки, перш ніж він перейшов на isinstanceпідхід, за винятком того +=, що для списків має інше значення, ніж +це.


2
Що ж, у вас є дві голоси, і ніхто не надав коментар. Я не прихильнився, але мені не подобається ваше рішення, оскільки: * Занадто багатослівний. Вам не потрібно визначати функцію для цього. * Дорогий. Ловлячи винятки, це не добре для продуктивності. * Схильний помилятися. Інший об’єкт може реалізувати додавання , перегляд рядка та підняття іншого типу винятку, який не є TypeError.
santiagobasulto

Також тут ви використовуєте підхід для набору качок, який є прекрасним, але в кінцевому підсумку викидайте та виловлюйте виняток, щоб дізнатись щось, що не прекрасно.
Олексій Тигарев

Це може бути єдино вірним способом розрізнити між рядковим та деяким іншим ітерабельним рядком. Можна було б шукати такі атрибути isalpha, але хто знає, які методи було б безпечно шукати?
clacke

Я зрозумів, що __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!
серпня
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.