Лучший способ абстрагировать данные о сезоне/шоу/эпизоде
В принципе, я написал 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
. Каждый из них является очень простым dict, который я могу легко добавить в функциональность (например, search()
на Show()
). Каждый из них имеет __setitem__
, __getitem_
и has_key
.
Это работает в основном отлично, я могу проверить шоу, если в нем есть этот сезон self.data
dict, если нет, 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
вызвать проблемы?
Ответы
Ответ 1
ОК, вам нужно 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")
Ответ 2
Почему бы не использовать 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'])
Ответ 3
Я сделал что-то подобное в прошлом и использовал XML-документ в памяти как быструю и грязную иерархическую базу данных для хранения. Вы можете хранить каждое шоу/сезон/эпизод в качестве элемента (соответственно вложенного) и атрибуты этих вещей как атрибуты xml для элементов. Затем вы можете использовать XQuery для возврата информации.
ПРИМЕЧАНИЕ: Я не парень Python, поэтому я не знаю, как выглядит ваша поддержка xml.
ПРИМЕЧАНИЕ 2:. Вам нужно будет профилировать это, потому что оно будет больше и медленнее, чем решение, которое у вас уже есть. Вероятно, достаточно, если вы выполняете обработку большого объема, тогда XML, вероятно, не будет вашим другом.
Ответ 4
Я не получаю эту часть здесь:
Это сработало хорошо, но не было простого способа проверить, должен ли существовать 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
что с этим связано?
Ответ 5
Bartosz/Чтобы уточнить "Это сработало хорошо, но не было простого способа проверить, должен ли существовать 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)
и т.д.
Это работает, но там, кажется, много повторяющегося кода (каждый класс в основном тот же, но вызывает другую ошибку)