2008-09-03 5 views
12

У меня есть метод в моем коде Python, который возвращает кортеж - строку из SQL-запроса. Предположим, у него есть три поля: (jobId, label, username)Разделение кортежей в Python - лучшая практика?

Для удобства передачи между функциями я передавал весь набор в качестве переменной, называемой «заданием». В конце концов, однако, я хочу получить бит, поэтому я использовал код следующим образом: (jobId, label, username) = job

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

Вот два моих лучших догадок: (JobId, этикетки, имя пользователя) = (работа [0], работа [1], работа [2]) ... но это не масштабируется хорошо, когда у вас есть 15 ... 20 полей

или для преобразования результатов из SQL-запроса в словарь сразу и передать его (я не контролирую тот факт, что он начинает жизнь как кортеж, это исправлено для меня)

ответ

13

Я бы сказал, что словарь, безусловно, лучший способ это сделать. Он легко расширяется, позволяет придать каждому значению разумное имя, а Python имеет множество встроенных языковых функций для использования и управления словарями. Если вам нужно добавить больше полей позже, все, что вам нужно изменить, это код, который преобразует кортеж в словарь и код, который фактически использует новые значения.

Например:

job={} 
job['jobid'], job['label'], job['username']=<querycode> 
+0

Смотри также http://code.activestate.com/recipes/81252/ – Jay

0

С кортежем всегда будет хлопоты, чтобы добавить или изменить поле. Вы правы, что словарь будет намного лучше.

Если вы хотите что-то со слегка более дружественным синтаксисом, вы можете взглянуть на ответы this question о простом «структурном» объекте. Таким образом, вы можете пройти вокруг объекта, скажем, job, и получить доступ к его полям даже легче, чем кортеж или Dict:

job.jobId, job.username = jobId, username 
3

Возможно, это является излишним для вашего случая, но я был бы соблазн создать «Работа ", который берет кортеж в качестве аргумента конструктора и имеет на нем соответствующие свойства. Затем я передавал примеры этого класса.

2

Я бы использовал словарь. Вы можете преобразовать кортеж в словаре так:

values = <querycode> 
keys = ["jobid", "label", "username"] 
job = dict([[keys[i], values [i]] for i in xrange(len(values))]) 

Это сначала создать массив [[ "JobId", VAL1], [ "ярлык", val2], [ "имя пользователя", val3]] и затем преобразуйте его в словарь. Если изменяется порядок результата или счет, вам просто нужно изменить список ключей для соответствия новому результату.

PS все еще свежий на Python сам, так что может быть лучше, чем это сделать.

+2

См Aaron Mäenpää ответ Zip. Обычная ошибка новичка в Python использует понимание списка, когда zip будет достаточно. –

-2

Как об этом:

class TypedTuple: 
    def __init__(self, fieldlist, items): 
     self.fieldlist = fieldlist 
     self.items = items 
    def __getattr__(self, field): 
     return self.items[self.fieldlist.index(field)] 

Вы могли бы сделать:

j = TypedTuple(["jobid", "label", "username"], job) 
print j.jobid 

Это должно быть легко поменять self.fieldlist.index(field) со словарем поиска позже ...просто отредактируйте свой метод __init__! Что-то вроде Staale.

13

@Staale

Существует лучший способ:

job = dict(zip(keys, values)) 
+0

Это тоже очень удобный код, единственная «проблема» - это перестройка кода для работы со словарями. –

2

старый вопрос, но так как никто не упомянул об этом я добавлю это из Python Cookbook:

Recipe 81252: Using dtuple for Flexible Query Result Access

Этот рецепт специально разработан для работы с результатами базы данных, а решение dtuple позволяет получить доступ к результатам по имени ИЛИ номеру индекса. Это позволяет избежать доступа ко всему по индексу, который очень трудно поддерживать, как указано в вашем вопросе.

5

Это старый вопрос, но ...

я предлагаю использовать именованный кортеж в этой ситуации: collections.namedtuple

Это является частью, в частности, что вы нашли бы полезным:

Подкласс не подходит для добавления новых сохраненных полей. Вместо этого просто создайте новый тип имени tuple из атрибута _fields.

+2

Другие преимущества: метод * namedtuple * использует меньше памяти, чем словарь, и поддерживает метод \ _replace() для обновления значений. –

+0

С технической точки зрения '_replace()' создает новый кортеж с замененными значениями, поскольку экземпляры классов 'namedtuple' неизменны, как обычные кортежи. – JAB

0

Если вы используете пакет MySQLdb, вы можете настроить объекты курсора для возврата dicts вместо кортежей.

import MySQLdb, MySQLdb.cursors 
conn = MySQLdb.connect(..., cursorclass=MySQLdb.cursors.DictCursor) 
cur = conn.cursor() # a DictCursor 
cur2 = conn.cursor(cursorclass=MySQLdb.cursors.Cursor) # a "normal" tuple cursor 
Смежные вопросы