Конкатенация querysets в список является самым простым подходом. Если база данных будет поражена для всего querysets так или иначе (например, потому что результат должен быть отсортирован), это не добавит далее стоимость.
from itertools import chain
result_list = list(chain(page_list, article_list, post_list))
Используя itertools.chain
быстрее, чем цикличное выполнение каждый список и элементы добавления один за другим, так как itertools
реализован в C. Это также использует меньше памяти, чем преобразование каждого queryset в список перед конкатенацией.
Теперь возможно отсортировать получающийся список, например, по дате (согласно просьбе в комментарии hasen j к другому ответу). Эти sorted()
функция удобно принимает генератор и возвращает список:
result_list = sorted(
chain(page_list, article_list, post_list),
key=lambda instance: instance.date_created)
при использовании Python 2.4 или позже можно использовать attrgetter
вместо лямбды. Я не забываю читать об этом являющийся быстрее, но я не видел значимой разности оборотов для миллиона списков объекта.
from operator import attrgetter
result_list = sorted(
chain(page_list, article_list, post_list),
key=attrgetter('date_created'))
Хорошо на простом английском:
Каждое шестнадцатеричное число 0x01,0x02,0x04,0x08 было выбрано ПОТОМУ ЧТО они закодированы как отдельные отдельные биты, заданные в двоичном формате. Ни одна из битовых карт не перекрывается, поэтому каждая из них может быть прочитана и установлена без влияния других битов. Добавление следующих комментариев к вашему коду проясняет, что происходит:
#define MSGINFO_ENABLE 0x01 // => 0001
#define MIME_ENABLE 0x02 // => 0010
#define FASTSTART_CODERS_IN_OFFERED 0x04 // => 0100
#define TRANSADDR_ENABLE 0x08 // => 1000
Теперь добавление комментария перед другой строкой показывает результат:
// VirtBoard.msginfo_mask |= 0001
// VirtBoard.msginfo_mask |= 0010
// VirtBoard.msginfo_mask |= 0100
// VirtBoard.msginfo_mask |= 1000
// ----
// VirtBoard.msginfo_mask == 1111
VirtBoard.msginfo_mask = MSGINFO_ENABLE |
MIME_ENABLE |
FASTSTART_CODERS_IN_OFFERED |
TRANSADDR_ENABLE;
Хотя комментарии к заданию проясняют, что происходит, как только вы понимаете, что происходит, комментарии как бы противоречат цели символического определения констант.
Можно подумать об этом следующим образом (значения показаны в двоичном формате):
MSGINFO_ENABLE = 0001
MIME_ENABLE = 0010
FASTSTART_CODERS_IN_OFFERED = 0100
TRANSADDR_ENABLE = 1000
Итак ...
1001 - это TRANSADDR_ENABLE
и MSGINFO_ENABLE
или
1101 - это все, но FASTSTART_CODERS_IN_OFFERED
Это вообще помогает? Нотация |
- это синтаксис C для установки правильного бита:
int something = 0;
something = MSGINFO_ENABLE | TRANSADDR_ENABLE;
- это синтаксис для установки только этих двух битов.
Ваша переменная msginfo_mask
, когда она представлена в виде двоичного числа (единицы и нули), используется как «маска» путем установки определенных битов в 1 (с использованием побитового ИЛИ) или очистка определенных битов до 0 (с помощью побитового И). Ваш фрагмент кода устанавливает одни биты в 1, оставляя другие без изменений. Маскирование можно сравнить с тем, как художник маскирует области, которые он не хочет раскрашивать.
Если вы посмотрите на #defines в верхней части кода, вы заметите, что каждое число представляет один бит при записи в двоичном формате:
#define MSGINFO_ENABLE 0x01 <-- 0001 in binary
#define MIME_ENABLE 0x02 <-- 0010 in binary
#define FASTSTART_CODERS_IN_OFFERED 0x04 <-- 0100 in binary
#define TRANSADDR_ENABLE 0x08 <-- 1000 in binary
Установка битов выполняется с помощью функции ИЛИ. Если вы поставите ИЛИ для бита с 1, результатом всегда будет 1. Если вы установите ИЛИ для бита с 0, исходное значение не изменится.
Итак, когда вы увидите:
msginfo_mask = MSGINFO_ENABLE | MIME_ENABLE |
FASTSTART_CODERS_IN_OFFERED | TRANSADDR_ENABLE;
То, что вы говорите является "
Программист устанавливает маску на определенное битовое значение. В этом случае:
VitBoard.msginfo_mask = 0x01 | 0x02 | 0x04 = 0x07
Предполагая, что код обрабатывает сообщения, когда приходит сообщение, они могут сравнить его с этой маской, чтобы увидеть, что включено в сообщении.
if((newMsg & VitBoard.msginfo_mask) == 0x07)
{
//do something related to mime enable, msginfo enable and faststart
}
Обратите внимание на оператор «&» для сравнения масок.
Другая часть заключается в том, что «или» маски вместе, вероятно, используются как переключатели для включить / отключить определенные функции. В написанных вами примерах это выглядит как возможный вывод на разных уровнях или частях кода.
Определенные маски можно использовать для проверки функциональности, чтобы увидеть, включена она или отключена. Например:
VirtBoard.msginfo_mask = MSGINFO_ENABLE | MIME_ENABLE ;
if ( VirtBoard.msginfo_mask & MSGINFO_ENABLE )
{
printf("Messages enabled\n";
}
if ( VirtBoard.msginfo_mask & TRANSADDR_ENABLE)
{
printf("Transaddress enabled\n");
}
В первом случае, поскольку маска MSGINFO_ENABLED была «или» и назначена переменной, когда вы применяете операцию «и» к переменной и маске MSGINOF_ENABLED, возвращается ненулевое значение, указывающее на истинность . Таким образом, будет выполнен оператор printf.
В случае второго if, поскольку TRANSADDR_ENABLE не был "или" в переменной, когда "
Бинарный оператор '|' - побитовый оператор ИЛИ; для каждого бита в двух входных словах, если любой бит равен 1, тогда соответствующий бит в результате будет равен 1:
0001 | 0010 = 0011
'|' Оператор обычно используется для установки отдельных битов в слове, например, в опубликованном вами фрагменте кода.
Бинарный оператор «&» является побитовым оператором «И»; для каждого бита в двух входных словах, если оба бита равны 1, тогда соответствующий бит в результате будет равен 1:
0101 & 0110 = 0100
Оператор '&' может использоваться для проверки, установлен ли бит. Например, чтобы проверить, установлен ли бит MSGINFO_ENABLE, вы должны сделать что-то вроде
if (VirtBoard.msginfo_mask & MSGINFO_ENABLE != 0)
{
/* MSGINFO_ENABLE bit is set, do something interesting */
}
Выражение
VirtBoard.msginfo_mask & MSGINFO_ENABLE
будет оцениваться как 1 (0x0001), если бит MSGINFO_ENABLE был установлен, в противном случае - 0.
Унарный оператор '~' - это побитовый оператор НЕ; для каждого бита во входном слове, соответствующий бит в результате устанавливается на противоположное значение:
~ 0001 = 1110
Вы можете использовать оператор '~' вместе с оператором '&', чтобы очистить отдельный бит. Например, если бы мы хотели очистить бит MSGINFO_ENABLE, мы бы сделали что-то вроде
VirtBoard.msginfo_mask = VirtBoard.msginfo_mask & ~MSGINFO_ENABLE;
, которое можно сократить до
VirtBoard.msginfo_mask &= ~MSGINFO_ENABLE;
. Отрицание MSGINFO_ ENABLE дает нам 1111111111111110 (при условии 16-битного целого числа без знака); так как все начальные биты равны 1, и если это противоречит маске VirtBoard.msginfo_, все биты, которые уже установлены, сохраняются; т.е. 0000000000001111 & 1111111111111110 = 0000000000001110.
Если бы мы хотели очистить биты MSGINFO _ENABLE и TRANSADDR _ENABLE, мы бы объединили все операторы следующим образом:
VirtBoard.msginfo_mask &= ~(MSGINFO_ENABLE | TRANSADDER_ENABLE)