этот питон может быть короче - PullRequest
1 голос
/ 19 ноября 2011

Я склонен увлекаться выражением кода максимально компактно и лаконично, не жертвуя эффективностью выполнения.

Вот мой код:

p_audio = plate.parts.filter(content__iendswith=".mp3") 
p_video = not p_audio and plate.parts.filter(content__iendswith=".flv") 
p_swf =   not p_audio and not p_video and plate.parts.filter(content__iendswith=".swf") 
extra_context.update({
  'p_audio':  p_audio and p_audio[0],
  'p_video':  p_video and p_video[0],
  'p_swf':    p_swf and   p_swf[0]
})

Существуют ли какие-либо гуру python / django, которые могут радикальносократить этот код?

Ответы [ 3 ]

3 голосов
/ 19 ноября 2011

На самом деле, стремясь к компактности и эффективности, вам удалось придумать ужасно неэффективный код.Это связано с тем, что когда вы ссылаетесь на p_audio или not p_audio, это приводит к тому, что этот набор запросов должен быть оценен - ​​а поскольку вы не разрезали его до этого, это означает, что весь фильтр извлекается из базы данных - например, все plate объекты, оканчивающиеся на mp3 и т. Д.

Прежде чем обращаться к значению этого запроса, убедитесь, что вы делаете срез для каждого запроса.Поскольку вас интересует компактность кода, вам, вероятно, сначала нужно нарезать [:1], чтобы получить набор запросов для одного объекта:

p_audio = plate.parts.filter(content__iendswith=".mp3")[:1]
p_video = not p_audio and plate.parts.filter(content__iendswith=".flv") [:1]
p_swf =   not p_audio and not p_video and plate.parts.filter(content__iendswith=".swf")[:1]

, а остальные могут остаться прежними.

Изменить, чтобы добавить Поскольку вас интересует только первый элемент каждого списка, о чем свидетельствует тот факт, что вы передаете только [0] из каждого элемента в контекст.Но в вашем коде not p_audio ссылается на исходный, не нарезанный набор запросов: и для определения истинного / ложного значения qs Django должен оценить его, который получает все соответствующие элементы из базы данных и преобразует их в объекты Python.Поскольку вы на самом деле не хотите эти объекты, вы выполняете гораздо больше работы, чем вам нужно.

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

2 голосов
/ 19 ноября 2011

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

kinds = (("p_audio", ".mp3"), ("p_video", ".flv"), ("p_swf", ".swf"))
extra_context.update((key, False) for key, _ in kinds)

for key, ext in kinds:
    entries = plate.parts.filter(content__iendswith=ext)
    if entries:
        extra_context[key] = entries[0]
        break
0 голосов
/ 19 ноября 2011

Просто добавьте это как еще один ответ, вдохновленный вышеописанным Pyroscope (поскольку мое редактирование должно быть рецензировано)

Последнее воплощение заключается в том, что система шаблонов Django просто игнорирует несуществующие элементы контекста, когда на них ссылаются, поэтому mp3 и т. Д. Ниже не нужно инициализировать как False (или 0). Итак, следующее отвечает всем функциональным возможностям кода из OP. Другая оптимизация заключается в том, что в качестве имен ключей используются mp3 и т. Д. (Вместо «p_audio» и т. Д.)

for key in ['mp3','flv','swf'] :
  entries = plate.parts.filter(content__iendswith=key)[:1]
  extra_context[key] = entries and entries[0]
  if extra_context[key] :
     break
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...