Лучший способ абстрагировать данные о сезоне / шоу / эпизоде
-
08-06-2019 - |
Вопрос
По сути, я написал API для www.thetvdb.com на Python.Текущий код можно найти здесь.
Он получает данные из API по запросу и должен каким-то образом сохранить данные и сделать их доступными, выполнив:
print tvdbinstance[1][23]['episodename'] # get the name of episode 23 of season 1
Каков "лучший" способ абстрагировать эти данные в рамках Tvdb()
класс?
Первоначально я использовал расширенный Dict()
это автоматически создавало подразделы (так что вы могли бы сделать x[1][2][3][4] = "something"
без необходимости делать if x[1].has_key(2): x[1][2] = []
и так далее)
Затем я просто сохранил данные, выполнив self.data[show_id][season_number][episode_number][attribute_name] = "something"
Это работало нормально, но не было простого способа проверить, работает ли x[3][24]
предполагалось, что он существует или нет (поэтому я не смог вызвать исключение season_not_found).
В настоящее время он использует четыре класса: ShowContainer
, Show
, Season
и Episode
.Каждый из них представляет собой очень простой диктант, в который я могу легко добавить дополнительную функциональность (the search()
функция включена Show()
например).У каждого есть __setitem__
, __getitem_
и has_key
.
Это работает в основном нормально, я могу проверить на Шоу, есть ли в нем этот сезон. self.data
диктовать, если нет, raise season_not_found
.Я также могу зарегистрироваться Season()
если в нем есть этот эпизод и так далее.
Проблема сейчас в том, что он представляет себя как dict, но не обладает всей функциональностью, и поскольку я переопределяю __getitem__
и __setitem__
функции, которые легко случайно рекурсивно вызвать __getitem__
(так что я не уверен, что расширение Dict
класс вызовет проблемы).
Другая небольшая проблема заключается в том, что добавление данных в dict требует намного больше работы, чем старый Dict
метод (который был self.data[seas_no][ep_no]['attribute'] = 'something'
).Видишь _setItem
и _setData
.Это не так уж плохо, поскольку в настоящее время это API-интерфейс только для чтения (поэтому пользователи API должны только извлекать данные, а не добавлять больше), но это вряд ли...Элегантный.
Я думаю, что система рядов классов, вероятно, является лучшим способом, но есть ли у кого-нибудь идея получше для хранения данных?И расширил бы ShowContainer
/etc классы с Dict
создавать проблемы?
Решение
Хорошо, все, что вам нужно, это classobj
из нового модуля.Это позволило бы вам динамически создавать классы исключений (classobj
принимает строку в качестве аргумента для имени класса).
import new
myexc=new.classobj("ExcName",(Exception,),{})
i=myexc("This is the exc msg!")
raise i
это дает вам:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.ExcName: This is the exc msg!
помните, что вы всегда можете получить имя класса через:
self.__class__.__name__
Итак, после некоторого искажения строки и конкатенации вы должны быть в состоянии получить соответствующее имя класса исключений и создать объект класса, используя это имя, а затем вызвать это исключение.
P.S.- вы также можете создавать строки, но это устарело.
raise(self.__class__.__name__+"Exception")
Другие советы
Почему бы не использовать SQLite?В Python есть хорошая поддержка, и вы можете писать SQL-запросы для получения данных.Вот документы Python для sqlite3
Если вы не хотите использовать SQLite, вы могли бы создать массив dicts.
episodes = []
episodes.append({'season':1, 'episode': 2, 'name':'Something'})
episodes.append({'season':1, 'episode': 2, 'name':'Something', 'actors':['Billy Bob', 'Sean Penn']})
Таким образом, вы добавляете метаданные к любой записи и очень легко выполняете поиск по ней
season_1 = [e for e in episodes if e['season'] == 1]
billy_bob = [e for e in episodes if 'actors' in e and 'Billy Bob' in e['actors']]
for episode in billy_bob:
print "Billy bob was in Season %s Episode %s" % (episode['season'], episode['episode'])
Я делал нечто подобное в прошлом и использовал XML-документ в памяти в качестве быстрой и грязной иерархической базы данных для хранения.Вы можете хранить каждое шоу / сезон / эпизод как элемент (вложенный соответствующим образом), а атрибуты этих объектов - как xml-атрибуты элементов.Затем вы можете использовать XQuery для получения информации обратно.
ПРИМЕЧАНИЕ: Я не разбираюсь в Python, поэтому не знаю, на что похожа ваша поддержка xml.
ПРИМЕЧАНИЕ 2: Вы захотите профилировать это, потому что оно будет больше и медленнее, чем решение, которое у вас уже есть.Вполне вероятно, что если вы выполняете какую-то крупномасштабную обработку, то XML, вероятно, не будет вашим другом.
Я не понимаю этой части здесь:
Это сработало нормально, но не было простого способа проверить, должен ли x [3] [24] существовать или нет (поэтому я не смог вызвать исключение season_not_found)
Есть способ сделать это - называется в:
>>>x={}
>>>x[1]={}
>>>x[1][2]={}
>>>x
{1: {2: {}}}
>>> 2 in x[1]
True
>>> 3 in x[1]
False
в чем, по-видимому, проблема с этим?
Бартош / Пояснить: "Это сработало нормально, но не было простого способа проверить, должен ли x [3] [24] существовать или нет".
x['some show'][3][24]
вернул бы 3 сезон, 24 серию "какого-то шоу".Если не было 3-го сезона, я хочу, чтобы псевдодикт поднял tvdb_seasonnotfound, если "some show" не существует, то поднимите tvdb_shownotfound
Текущая система состоит из серии классов, каждый из которых имеет __getitem__
- Показывать чеки if self.seasons.has_key(requested_season_number)
, проверка класса сезона if self.episodes.has_key(requested_episode_number)
и так далее.
Это работает, но, похоже, там много повторяющегося кода (каждый класс в основном один и тот же, но выдает разную ошибку)