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

StackOverflow https://stackoverflow.com/questions/41701

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

Это было полезно?

Решение

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

Например:

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

Другие советы

@Стаале

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

job = dict(zip(keys, values))

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

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

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

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

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

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

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

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

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

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

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

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

job.jobId, job.username = jobId, username

Если вы используете пакет MySQLdb, вы можете настроить свои объекты cursor так, чтобы они возвращали 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

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

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__ метод!Что-то вроде того, что делает Стаале.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top