-
Случайно столкнулся и пропарился пару часов.
Сказывается изучение питона с помощью гугления :(
Мне казалось что в питоне все ссылки, поэтому был написан такой код:
который все отрабатывал правильно, но поля на выходе в row не изменялись.def convert_row( row ):
for attr in row:
if isinstance( attr, str ):
attr = unicode( attr, 'cp1251' )
elif isinstance( attr, Property):
attr = str(attr)
В результате такой код работает, но он мне не нравится:
Подскажите какую основополагающую вешь я не понимаю?def convert_row( row ):
for i in range(0,len(row)):
if isinstance( row[i], str ):
row[i] = unicode( row[i], 'cp1251' )
elif isinstance( row[i], Property):
row[i] = str(row[i])
UPDATE:
Код правил, но так и не понял как сделать чтобы квадратные скобки отображались в коде. -
А что есть 'row'?
Почему нельзя явно вернуть результат из функции?
Ну и если row - список, то первый вариант кода тоже бы заработал. -
def convert_row( row ): for attr in row: if isinstance( attr, str ): attr = unicode( attr, 'cp1251' )Вот на этом месте вы не меняете объект, на который показывает локальное имя attr. Вместо этого вы локальному имени attr присваиваете новый локальный объект — юникод-строку, созданную на основе его старого значения. В общем случае вы и не можете так сделать, потому что объект под attr может быть вообще неизменяемым (immutable). В частности, строки как раз неизменяемые.
Обходится это двумя способами.
Примерно так, как у вас во втором примере, явно перезаписывая row[i]:
def convert_row(row): for i, attr in enumerate(row): if isinstance(attr, str): row[i] = unicode(attr, 'cp1251') elif isinstance(attr, Property): row[i] = str(attr)Но этот подход совсем не питоний, никто не меняет списки прямо по месту.
Лучше просто создать новый список на основе старого, сделав функцию, которая работает не над списком, а над отдельным атрибутом. По сути это классический "map".
def convert_attr(attr): if isinstance(attr, str): return unicode(attr, 'cp1251') elif isinstance(attr, Property): return str(attr) row = [convert_attr(attr) for attr in row] # или то же ещё короче: row = map(convert_attr, row)
К слову, в этом коде и других непитонизмов достаточно. Использование
isinstanceвсегда подозрительно, стоит посмотреть, нельзя ли всё отрефакторить так, чтобы объекты использовались как есть. Также, после такого преобразования у вас получится список с разными типами объектов (unicodeиstr), что тоже не очень красиво. -
Спасибо Иван.
К сожалению с помощью питона пытаюсь привести в REST старую CORBA систему.
Или к счастью.
Начал я действительно с map.
А закончил таким непитонизмом. Row это действительно список содержащий объекты разных типов. Для примера строка БД. Эту типизацию хочется сохранить. Но строки хочется отдавать в юникоде, а не в 1251 как они приходят из корбы.
Конвертить по индексу, только конкретные атрибуты не получается тоже, потому что заранее неизвестен порядок запроса. А копировать весь результат не позволяет бережное отношение к памяти :))
Есть идеи? Хотя даже пример с enumerate меня почти примиряет с жизнью -
Переделал обратно на map
получилось читабельнее. Пока это важнее памяти. -
За память вы совсем зря беспокоитесь. Garbage collection вполне себе хорошо работает. Я бы даже сказал, что на Питоне невозможно эффективно писать, если думать о таких вещах. Это же не Си.
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

