2012-02-16 3 views
3

나는 f 함수에 따라 a[i: j] 요소를 변경하고자하는 목록이 a입니다. 순진한 방식보다 더 잘할 수 있습니까?for 루프의 목록 요소 수정하기

for index in range(i, j): 
    a[index] = f(a) 

[함으로써 나는 map(f, a)에 가까운 무언가, 또는 빨리 뭔가를 의미하는 더 나은.]

+0

당신은'range''이상 xrange'을 (http://stackoverflow.com/a/135114/589206 참조) 선호 있습니다

또한, 여기가 해당 코드 있다는 증거입니다. – hochl

+0

나는 이것이 당신의 의도에 더 가깝다고 생각한다 :'for index, ai in enumerate (a [i : j], start = i) : a [index] = f (ai)' – hughdbrown

답변

3
당신은 슬라이스에 할당 할 수있는

:

a[i:j] = map(f, a[i:j]) 
+1

@Randomblue 시도해 보셨습니까? –

+0

@Randomblue가 조각을 읽습니다. http://docs.python.org/library/stdtypes.html#mutable-sequence-types "i ~ j의 s [i : j] = t 슬라이스가 iterable t의 내용으로 대체됩니다." – hughdbrown

1

사용 지능형리스트 ...

a[i:j] = [f(ai) for ai in a[i:j]] 

또는 map 상당 ...

a[i:j] = map(f, a[i:j]) 
+0

이것은 시간이 얼마나 좋은가? – Randomblue

+1

유스 케이스에서 테스트해야합니다. 아마도 i와 j의 값과 요소의 유형에 따라 달라질 것입니다. –

2

타이밍 연습을하지는 않지만 다양한 옵션이 어떤 내부 코드로 바뀌는 지 보여 드리겠습니다. 코드는 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]