Разделение кортежей в Python - лучшая практика? - PullRequest
13 голосов
/ 03 сентября 2008

В моем коде Python есть метод, который возвращает кортеж - строку из запроса SQL. Допустим, у него есть три поля: (jobId, метка, имя пользователя)

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

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

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

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

Ответы [ 9 ]

14 голосов
/ 03 сентября 2008

@ Staale

Есть лучший способ:

job = dict(zip(keys, values))
13 голосов
/ 03 сентября 2008

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

Например:

job={}
job['jobid'], job['label'], job['username']=<querycode>
5 голосов
/ 17 июля 2009

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

Я бы предложил использовать именованный кортеж в этой ситуации: collection.namedtuple

Эта часть, в частности, вам будет полезна:

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

3 голосов
/ 03 сентября 2008

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

2 голосов
/ 22 декабря 2008

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

Рецепт 81252: Использование dtuple для гибкого доступа к результатам запроса

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

2 голосов
/ 03 сентября 2008

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

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

Сначала будет создан массив [["jobid", val1], ["label", val2], ["username", val3]], а затем преобразован в словарь. Если порядок результатов или количество изменяется, вам просто нужно изменить список ключей, чтобы соответствовать новому результату.

PS Сам по-прежнему свеж на Python, так что, возможно, есть лучшие способы сделать это.

0 голосов
/ 09 апреля 2010

Если вы используете пакет 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
0 голосов
/ 03 сентября 2008

Как насчет этого:

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 делает.

0 голосов
/ 03 сентября 2008

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

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

job.jobId, job.username = jobId, username
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...