2010-02-24 4 views
5

불필요한 슬라이스 복사를 방지하는 것은 다음과 같은 경우에 무의미 슬라이스 복사를 방지하기위한 공통의 관용구가 있습니다. extend에게주는 새로운 슬라이스를 메모리에 작성하는 대신 "이 현재 오브젝트의 범위 만 사용"이라고 말하고 싶습니다.파이썬

>>> a = bytearray(1000000)  # a million zero bytes 
>>> a[0:900000].count(b'\x00') # expensive temporary slice 
900000 
>>> a.count(b'\x00', 0, 900000) # helpful start and end parameters 
900000 

을하지만, 많은 내 첫 번째 예에서 extend처럼,이 기능이없는 :

일부 방법은 예를 count를 들어, 슬라이스 매개 변수와 함께 당신을 도울 것입니다.

많은 응용 프로그램에서 내가 말하고자하는 것은 마이크로 최적화라고 생각하기 때문에 누구나 묻기 전에 - 예, 응용 프로그램을 프로파일 링했습니다. 내 경우에 대해 걱정할만한 가치가 있습니다.

아래에 '해결책'이 하나 있지만 더 좋은 아이디어는 언제든지 환영합니다.

답변

5

슬라이스를 복사 buffer 객체를 피한다 만들기,하지만 짧은 조각을 위해 그냥 복사 할 것이 더 효율적입니다 : 여기

>>> a.extend(buffer(b, 14, 6)) 
>>> a 
bytearray(b'hello world') 

메모리로 만들어진 하나의 복사본 만 거기를하지만, buffer를 만드는 비용 객체는 저장을 제거합니다. 그것은 더 큰 조각을 위해 더 나을 것입니다. 이 방법이 전체적으로 더 효율적 이도록 슬라이스가 얼마나 커야할지 모르겠습니다. 파이썬 3 (선택적 파이썬 2.7에서) 당신이 대신 memoryview 객체가 필요 거라고

참고 :

>>> a.extend(memoryview(b)[14:20]) 
+0

버퍼는 버퍼 인터페이스를 지원하는 객체에 적합한 선택입니다. 대개 소량의 경우 50 % 이상이 여전히 작은 금액이기 때문에 작은 케이스의 경우 특별한 대소 문자를 구분할 가치가 없습니다 (대부분의 사용 사례가 작은 경우 제외). –

2

itertoolsislice 있습니다. islice에는 count 메소드가 없으므로 슬라이스를 복사하지 않으려는 다른 경우에 유용합니다. 여러분이 지적했듯이 - 카운트에는 그 메커니즘이 있습니다.

>>> from itertools import islice 
>>> a = bytearray(1000000) 
>>> sum(1 for x in islice(a,0,900000) if x==0) 
900000 
>>> len(filter(b'\x00'.__eq__,islice(a,0,900000))) 
900000 

>>> a=bytearray(b"hello") 
>>> b = bytearray(b'goodbye, cruel world.') 
>>> a.extend(islice(b,14,20)) 
>>> a 
bytearray(b'hello world') 
+0

'islice'는 좋은 대안입니다. 방금 몇 가지 빠른 테스트를했는데'extend'와 함께 사용하면'buffer'만큼 빠르지 만 슬라이스를 사용하는 것보다 훨씬 더 느립니다. 50 만 개 요소도 있습니다 ... –