2016-11-07 29 views
8

Patrzę na 3rd party API i mają następujący fragment kodu:Znaczenie " 0 0" w języku Python?

def array_u16 (n): return array('H', '\0\0'*n) 

Rozumiem, że '\0' oznacza NULL, robi '\0\0' mają żadnego specjalnego znaczenia, czy też po prostu oznaczać 2 NULL s?

Odpowiedz

6

Wygląda na to, że ta funkcja zwraca tablicę złożoną z 16 bitów; tak więc \0\0 prawdopodobnie oznacza tworzenie dwóch bajtów (czyli 16 bitów) danych. Innymi słowy, zwraca n słów o dwóch bajtach.

10

Klasa array akceptuje znak formatu (nazywany kodem typologicznym), po którym następuje inicjator. H oznacza niepodpisany krótki, o minimalnym rozmiarze 2 bajtów, więc '\0\0' spełnia to. Część * n inicjuje całą tablicę na NULL bajtów.

7

Po prostu zapewnia, że ​​dwa bajty są dostarczane n razy, więc rozmiar tablicy będzie równy n. Jeśli podano '\0', uzyskana macierz będzie miała size == n//2 (due to the type-code 'H' requiring 2 bytes); to jest oczywiście sprzeczne z intuicją:

>>> array('H', '\0' * 10) # 5 elements 
array('H', [0, 0, 0, 0, 0]) 
>>> array('H', '\0\0' * 10) # 10 elements 
array('H', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) 

zauważyć, że w Pythonie 3, jeśli potrzebujesz samą fragment pracować ci moszczuprovide a bytes object jak initializer argument array:

>>> array('H', b'\0\0' * 10) 
array('H', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) 

As nie możesz również podać ciągu znaków u'' w Pythonie 2. Poza tym zachowanie pozostaje dokładnie takie samo.

Tak więc '\0\0' jest ze względów praktycznych, nic więcej. Żadne semantyki nie są dołączone do '\0\0'.

Brak semantyka są naprawdę przywiązany do '\0' albo (jak robią to, na przykład, C) '\0'to tylko kolejny ciąg w Pythonie.


Jako dalszy przykład tego problemu, trochę inicjacji tablicy z typu kodu 'I' do unsigned int z minimum 2 bajtów ale 4 na 64bit buduje Pythonie.

W duchu fragmencie już dostarczonych, można zainicjować tablicę robiąc coś takiego:

>>> array('I', b'\0\0\0\0' * 10) 
array('I', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) 

Tak, cztery razy ciąg b'\0' dostać 10 elementy.


Jako końcowy notatki - następujące czasy są wykonywane w Pythonie 3, ale 2 jest taka sama - można się zastanawiać, dlaczego użył '\0\0\' * n zamiast bardziej intuicyjne wyglądające [0] * n zainicjować tablica. Cóż, to całkiem szybciej:

n = 10000 
%timeit array('I', [0]*n) 
1000 loops, best of 3: 212 µs per loop 

%timeit array('I', b'\0\0\0\0'* n) 
100000 loops, best of 3: 6.36 µs per loop 

Oczywiście, można to zrobić lepiej (dla typu kodów innych niż 'b') poprzez podawanie bytearray do array. Jednym ze sposobów, aby zainicjować a bytearray is by providing an int as the number of items to initialize bajtami null:

%timeit array('I', bytearray(n)) 
1000000 loops, best of 3: 1.72 µs per loop 

ale jeśli ja pamiętam, bytearray(int) sposobem inicjowania ByteArray może się przestarzałe w 3.7+ :-).