ОБНОВЛЕНИЕ:
Идея сделать встроенные строки не повторяемыми была предложена на python.org в 2006 году. Мой вопрос отличается тем, что я пытаюсь подавить эти функции только время от времени; тем не менее, вся эта ветка весьма актуальна.
Вот критические комментарии Гвидо, реализовавшие non -iterable str
на пробной основе:
[...] Я реализовал это (это было действительно просто), но затем обнаружил, что мне нужно исправить множество мест, которые повторяются по строкам. Например:
Парсер и компилятор sre используют такие вещи, как set ("0123456789"), а также перебирают символы входящего регулярного выражения для его анализа.
diffflib имеет API, определенный либо для двух списков строк (типичный построчный diff файла), либо для двух строк (типичный внутристрочный diff), либо даже для двух списков чего-либо (для обобщенного сравнения последовательностей) .
небольшие изменения в optparse.py, textwrap.py, string.py.
И я даже не на том этапе, когда фреймворк regrtest.py даже работает (из-за проблемы с diffflib).
Я отказываюсь от этого проекта; это патч SF 1471291. Я больше не поддерживаю эту идею; это просто непрактично, и предположение о том, что существует несколько веских причин для итерации по строке, было опровергнуто случаями использования, которые я нашел как в sre, так и в difflib.
ОРИГИНАЛЬНЫЙ ВОПРОС:
Хотя это изящная особенность языка, что строка является итерируемой, в сочетании с утиной печатью это может привести к катастрофе:
# record has to support [] operation to set/retrieve values
# fields has to be an iterable that contains the fields to be set
def set_fields(record, fields, value):
for f in fields:
record[f] = value
set_fields(weapon1, ('Name', 'ShortName'), 'Dagger')
set_fields(weapon2, ('Name',), 'Katana')
set_fields(weapon3, 'Name', 'Wand') # I was tired and forgot to put parentheses
Никакого исключения не возникнет, и нет простого способа поймать это, кроме как протестировать isinstance(fields, str)
во множестве мест. В некоторых случаях поиск этой ошибки может занять очень много времени.
Я хочу полностью отключить обработку строк как итерацию в моем проекте. Это хорошая идея? Можно ли это сделать легко и безопасно?
Возможно, я мог бы создать подкласс встроенного str
, так что мне нужно было бы явно вызвать get_iter()
, если бы я хотел, чтобы его объект обрабатывался как повторяемый. Затем всякий раз, когда мне нужен строковый литерал, я вместо этого создаю объект этого класса.
Вот несколько косвенно связанных вопросов:
Как узнать если переменная Python является строкой или списком?
как указать, что переменная является повторяемой, но не строка
isinstance(fields, str)
- вам вряд ли когда-нибудь понадобится способность создавать свои собственные типы, которые крякают, как строка. Либо сделайтеfields
последним аргументом varargs. (Хотя это не поможет, если вы устанете и забудете, что не должны заключать это в круглые скобки.) - person millimoose   schedule 07.02.2012