Ответ 1
Q1: Да, да, да и да. Или, по крайней мере, они ведут себя так. Это немного отличается, если вы посмотрите на байт-код. Разберите этот код (Python 2.7):
def list_comp(l):
return [x+1 for x in l]
def dict_comp(l):
return {x+1:0 for x in l}
def set_comp(l):
return {x+1 for x in l}
def generator(l):
return (x+1 for x in l)
Это то, что вы получаете:
Disassembly of list_comp:
2 0 BUILD_LIST 0
3 LOAD_FAST 0 (l)
6 GET_ITER
>> 7 FOR_ITER 16 (to 26)
10 STORE_FAST 1 (x)
13 LOAD_FAST 1 (x)
16 LOAD_CONST 1 (1)
19 BINARY_ADD
20 LIST_APPEND 2
23 JUMP_ABSOLUTE 7
>> 26 RETURN_VALUE
Disassembly of dict_comp:
5 0 LOAD_CONST 1 (<code object <dictcomp> at 029DEE30)
3 MAKE_FUNCTION 0
6 LOAD_FAST 0 (l)
9 GET_ITER
10 CALL_FUNCTION 1
13 RETURN_VALUE
Disassembly of set_comp:
8 0 LOAD_CONST 1 (<code object <setcomp> at 029DECC8)
3 MAKE_FUNCTION 0
6 LOAD_FAST 0 (l)
9 GET_ITER
10 CALL_FUNCTION 1
13 RETURN_VALUE
Disassembly of generator:
11 0 LOAD_CONST 1 (<code object <genexpr> at 02A8FD58)
3 MAKE_FUNCTION 0
6 LOAD_FAST 0 (l)
9 GET_ITER
10 CALL_FUNCTION 1
13 RETURN_VALUE
Байт-код практически не отличается от решения, связанного с выражением, установкой и генератором. Все они загружают объект кода (<dictcomp>
, <setcomp>
или <genexpr>
), а затем выводят из него вызывающую функцию. Понимание списков отличается тем, что генерирует байт-код, соответствующий вашему пониманию списка. На этот раз он интерпретируется и, следовательно, не является родным.
Q2: На самом деле он не учитывает повторяющиеся значения, так как создает понимание с указанным вами списком. И затем он создает набор с пониманием.
О сроках: List/Dict/Установить понимание, как правило, быстрее, чем что-либо еще. Даже если они интерпретируются, генерируемый байт-код оптимизирован для большинства случаев со специальными инструкциями байт-кода, такими как SET_ADD
, LIST_APPEND
или MAP_ADD
.