Подтвердить что ты не робот

Разделение кортежей в Python - лучшая практика?

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

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

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

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

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

4b9b3361

Ответ 1

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

Например:

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

Ответ 2

@Staale

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

job = dict(zip(keys, values))

Ответ 3

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

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

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

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

Ответ 4

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

Ответ 5

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

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, поэтому может быть лучше, чем это сделать.

Ответ 6

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

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

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

Ответ 7

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

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

job.jobId, job.username = jobId, username

Ответ 8

Если вы используете пакет 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

Ответ 9

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

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.