Как маскирование работает

Конкатенация 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'))
11
задан KPexEA 7 August 2009 в 02:42
поделиться

6 ответов

Хорошо на простом английском:

Каждое шестнадцатеричное число 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;

Хотя комментарии к заданию проясняют, что происходит, как только вы понимаете, что происходит, комментарии как бы противоречат цели символического определения констант.

16
ответ дан 3 December 2019 в 02:11
поделиться

Можно подумать об этом следующим образом (значения показаны в двоичном формате):

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; 

- это синтаксис для установки только этих двух битов.

7
ответ дан 3 December 2019 в 02:11
поделиться

Ваша переменная 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;

То, что вы говорите является "

4
ответ дан 3 December 2019 в 02:11
поделиться

Программист устанавливает маску на определенное битовое значение. В этом случае:

VitBoard.msginfo_mask = 0x01 | 0x02 | 0x04 = 0x07

Предполагая, что код обрабатывает сообщения, когда приходит сообщение, они могут сравнить его с этой маской, чтобы увидеть, что включено в сообщении.

if((newMsg & VitBoard.msginfo_mask) == 0x07)
{
  //do something related to mime enable, msginfo enable and faststart
}

Обратите внимание на оператор «&» для сравнения масок.

2
ответ дан 3 December 2019 в 02:11
поделиться

Другая часть заключается в том, что «или» маски вместе, вероятно, используются как переключатели для включить / отключить определенные функции. В написанных вами примерах это выглядит как возможный вывод на разных уровнях или частях кода.

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

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 не был "или" в переменной, когда "

2
ответ дан 3 December 2019 в 02:11
поделиться

Бинарный оператор '|' - побитовый оператор ИЛИ; для каждого бита в двух входных словах, если любой бит равен 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)
3
ответ дан 3 December 2019 в 02:11
поделиться