Строка именованных к списку

Как бы я преобразовал строку именованных кортежей в список?

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

>>> Point = namedtuple("Point", "x y", verbose = False)
>>> p = Point(3, 5)
>>> points = []
>>> points.append(Point(4, 7))
>>> points.append(Point(8, 9))
>>> points.append(p)
>>> p.x
3
>>> print points
[Point(x=4, y=7), Point(x=8, y=9), Point(x=3, y=5)]

Мой список именованных кортежей выглядит примерно так: ^^^^, но у него 6 аргументов вместо 2, показанных выше. Изменить - аргументы - логические значения, целые числа и строки.

Я попытался сопоставить, но я получил следующую ошибку:

>>> string = str(points)
>>> l = string.strip("[]")
>>> p = map(Point._make, l.split(", "))

Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
p = map(Point._make, l.split(", "))
File "<string>", line 17, in _make
TypeError: Expected 2 arguments, got 9

Я открыт для других более простых способов сделать это.

3 ответа

Решение

В конечном счете, как это сделать, может быть делом вкуса.

JSON

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

>>> import json  # simple json is better bit I didn't want to force an install
>>> from collections import namedtuple
>>> Point = namedtuple("Point", "x y", verbose = False)
>>> p = Point(3,4)
>>> json.dumps(p._asdict())
'{"x": 3, "y": 4}'
>>> s = json.dumps(p._asdict())
>>> json.loads(s)  # not there yet cause thisis a dict
{u'y': 4, u'x': 3}   # but it is a dict that can create a Point
>>> Point(**json.loads(s))
Point(x=3, y=4)    

Соленый огурец

Pickle не будет работать, если вы не определите состояние атрибута (см. __getstate__ в документах). Это "Ницца" в фазе загрузки, следуя сверху:

import pickle

# Point.__getstate__=lambda self: self._asdict() # not needed as per @simon's comment thx simon
>>> pickle.dumps(p)
"ccopy_reg\n_reconstructor\np0\n(c__main__\nPoint\np1\nc__builtin__\ntuple\np2\n(I3\nI4\ntp3\ntp4\nRp5\nccollections\nOrderedDict\np6\n((lp7\n(lp8\nS'x'\np9\naI3\naa(lp10\nS'y'\np11\naI4\naatp12\nRp13\nb."
s = pickle.dumps(p)
>>> pickle.loads(s)
Point(x=3, y=4)

Eval

Я бы не рекомендовал использовать eval или exec. Если вы идете по этому маршруту проверить ast.literal_eval() и проверить некоторые из связанных с SO ответов, таких как безопасность Python Eval

Основываясь на ответе Фила Купера, вы можете хранить ваши объекты в формате json:

>>> import json

>>> points_str = json.dumps([x._asdict() for x in points])
[{"x": 4, "y": 7}, {"x": 8, "y": 9}, {"x": 1, "y": 2}]

>>> points2 = [Point(**x) for x in json.loads(points_str)]
[Point(x=4, y=7), Point(x=8, y=9), Point(x=1, y=2)]

Другой странный способ сделать это - использовать exec:

>>> points_str = repr(points)
'[Point(x=4, y=7), Point(x=8, y=9), Point(x=1, y=2)]'

>>> exec "points2 = %s" % points
>>> points2
[Point(x=4, y=7), Point(x=8, y=9), Point(x=1, y=2)]

Я бы порекомендовал вам использовать такие модули, как pickle что позволяет хранить объекты Python в файлах.

Кстати, я не уверен, если namedtuple будет работать с pickle, если это так, и источник данных не является неизвестным, то вы также можете использовать eval с repr:

помочь на repr:

>>> print repr.__doc__
repr(object) -> string

Return the canonical string representation of the object.
For most object types, eval(repr(object)) == object.

Пример:

>>> repr(points)
'[Point(x=4, y=7), Point(x=8, y=9), Point(x=3, y=5)]'
>>> eval(repr(points))
[Point(x=4, y=7), Point(x=8, y=9), Point(x=3, y=5)]
Другие вопросы по тегам