나는 f
함수에 따라 a[i: j]
요소를 변경하고자하는 목록이 a
입니다. 순진한 방식보다 더 잘할 수 있습니까?for 루프의 목록 요소 수정하기
for index in range(i, j):
a[index] = f(a)
[함으로써 나는 map(f, a)
에 가까운 무언가, 또는 빨리 뭔가를 의미하는 더 나은.]
나는 f
함수에 따라 a[i: j]
요소를 변경하고자하는 목록이 a
입니다. 순진한 방식보다 더 잘할 수 있습니까?for 루프의 목록 요소 수정하기
for index in range(i, j):
a[index] = f(a)
[함으로써 나는 map(f, a)
에 가까운 무언가, 또는 빨리 뭔가를 의미하는 더 나은.]
:
a[i:j] = map(f, a[i:j])
@Randomblue 시도해 보셨습니까? –
@Randomblue가 조각을 읽습니다. http://docs.python.org/library/stdtypes.html#mutable-sequence-types "i ~ j의 s [i : j] = t 슬라이스가 iterable t의 내용으로 대체됩니다." – hughdbrown
사용 지능형리스트 ...
a[i:j] = [f(ai) for ai in a[i:j]]
또는 map
상당 ...
a[i:j] = map(f, a[i:j])
이것은 시간이 얼마나 좋은가? – Randomblue
유스 케이스에서 테스트해야합니다. 아마도 i와 j의 값과 요소의 유형에 따라 달라질 것입니다. –
타이밍 연습을하지는 않지만 다양한 옵션이 어떤 내부 코드로 바뀌는 지 보여 드리겠습니다. 코드는 naive
입니다. 슬라이스가 l 값인 맵 기반 솔루션은 map_lvalue_slice
입니다. l- 값으로 슬라이스가있는 목록 이해는 list_comp_lvalue_slice
입니다. 그들은 아마 대부분의 최적화 된 사용하고 있기 때문에, 제 생각에 가장 바람직한 바람직 꽉 루프에서, C 코드에 가장 빠른 해결이
>>> from dis import dis
>>>
>>> def naive(a, f, i, j):
... for index, ai in enumerate(a[i:j], start=i):
... a[index] = f(ai)
...
>>> def map_lvalue_slice(a, f, i, j):
... a[i:j] = map(f, a[i:j])
...
>>> def list_comp_lvalue_slice(a, f, i, j):
... a[i:j] = [f(ai) for ai in a[i:j]]
...
>>> def tuple_lvalue_slice(a, f, i, j):
... a[i:j] = tuple(f(ai) for ai in a[i:j])
...
>>> dis(naive)
2 0 SETUP_LOOP 55 (to 58)
3 LOAD_GLOBAL 0 (enumerate)
6 LOAD_FAST 0 (a)
9 LOAD_FAST 2 (i)
12 LOAD_FAST 3 (j)
15 SLICE+3
16 LOAD_CONST 1 ('start')
19 LOAD_FAST 2 (i)
22 CALL_FUNCTION 257
25 GET_ITER
>> 26 FOR_ITER 28 (to 57)
29 UNPACK_SEQUENCE 2
32 STORE_FAST 4 (index)
35 STORE_FAST 5 (ai)
3 38 LOAD_FAST 1 (f)
41 LOAD_FAST 5 (ai)
44 CALL_FUNCTION 1
47 LOAD_FAST 0 (a)
50 LOAD_FAST 4 (index)
53 STORE_SUBSCR
54 JUMP_ABSOLUTE 26
>> 57 POP_BLOCK
>> 58 LOAD_CONST 0 (None)
61 RETURN_VALUE
>>>
>>> dis(map_lvalue_slice)
2 0 LOAD_GLOBAL 0 (map)
3 LOAD_FAST 1 (f)
6 LOAD_FAST 0 (a)
9 LOAD_FAST 2 (i)
12 LOAD_FAST 3 (j)
15 SLICE+3
16 CALL_FUNCTION 2
19 LOAD_FAST 0 (a)
22 LOAD_FAST 2 (i)
25 LOAD_FAST 3 (j)
28 STORE_SLICE+3
29 LOAD_CONST 0 (None)
32 RETURN_VALUE
>>>
>>> dis(list_comp_lvalue_slice)
2 0 BUILD_LIST 0
3 LOAD_FAST 0 (a)
6 LOAD_FAST 2 (i)
9 LOAD_FAST 3 (j)
12 SLICE+3
13 GET_ITER
>> 14 FOR_ITER 18 (to 35)
17 STORE_FAST 4 (ai)
20 LOAD_FAST 1 (f)
23 LOAD_FAST 4 (ai)
26 CALL_FUNCTION 1
29 LIST_APPEND 2
32 JUMP_ABSOLUTE 14
>> 35 LOAD_FAST 0 (a)
38 LOAD_FAST 2 (i)
41 LOAD_FAST 3 (j)
44 STORE_SLICE+3
45 LOAD_CONST 0 (None)
48 RETURN_VALUE
>>>
>>> dis(tuple_lvalue_slice)
2 0 LOAD_GLOBAL 0 (tuple)
3 LOAD_CLOSURE 0 (f)
6 BUILD_TUPLE 1
9 LOAD_CONST 1 (<code object <genexpr> at 0xb748dc38, file "<stdin>", line 2>)
12 MAKE_CLOSURE 0
15 LOAD_FAST 0 (a)
18 LOAD_FAST 2 (i)
21 LOAD_FAST 3 (j)
24 SLICE+3
25 GET_ITER
26 CALL_FUNCTION 1
29 CALL_FUNCTION 1
32 LOAD_FAST 0 (a)
35 LOAD_FAST 2 (i)
38 LOAD_FAST 3 (j)
41 STORE_SLICE+3
42 LOAD_CONST 0 (None)
45 RETURN_VALUE
솔루션을 : 목록의 이해에 관한 해결책은 튜플을 사용하고 tuple_lvalue_slice
라고 C 코드 및 우세하게 해석 된 명령어가 아닙니다. 코드를 l-value 솔루션으로 사용하는 슬라이스를 선호하고지도 작성에 집중할 수도 있습니다.
>>> i, j = 4, 8
>>> def f(ai):
... return -ai
...
>>> for fn in (naive, map_lvalue_slice, list_comp_lvalue_slice, tuple_lvalue_slice):
... a = range(10)
... fn(a, f, i, j)
... print "%-40s: %r" % (fn.__name__, a)
...
naive : [0, 1, 2, 3, -4, -5, -6, -7, 8, 9]
map_lvalue_slice : [0, 1, 2, 3, -4, -5, -6, -7, 8, 9]
list_comp_lvalue_slice : [0, 1, 2, 3, -4, -5, -6, -7, 8, 9]
tuple_lvalue_slice : [0, 1, 2, 3, -4, -5, -6, -7, 8, 9]
당신은'range''이상 xrange'을 (http://stackoverflow.com/a/135114/589206 참조) 선호 있습니다
또한, 여기가 해당 코드 있다는 증거입니다. – hochl
나는 이것이 당신의 의도에 더 가깝다고 생각한다 :'for index, ai in enumerate (a [i : j], start = i) : a [index] = f (ai)' – hughdbrown