2012-10-31 6 views
5

In una disconnessione python, ho visto una funzione per convertire la stringa IP in un intero in modo di programmazione funzionale. Ecco the Link.Come capire il codice di programmazione funzionale per convertire la stringa IP in un intero?

La funzione è implementata in una singola riga.

def ipnumber(ip): 
    return reduce(lambda sum, chunk: sum <<8 | chunk, map(int, ip.split("."))) 

Tuttavia, ho poche idee sulla programmazione funzionale. Qualcuno potrebbe spiegare la funzione in dettaglio? Ho una certa conoscenza di "mappa" e "riduzione". Ma non so come "|" e "chunk" significa qui.

Grazie.

+0

come nota a margine, pitone include questo tipo di batterie: 'struct.unpack (, socket.inet_aton (ip 'I!')) [ 0] ' – georg

+0

Mi chiedo quale sia la differenza di prestazioni? – Keith

risposta

13

sum e chunk sono argomenti della funzione lambda passata a reduce. | è il binario o l'operatore.

La cosa funziona così:

  • ip.split(".") restituisce una lista di stringhe, ciascuna corrispondente ad un pezzo della stringa tratteggiata ("192.168.0.1" =>["192", "168", "0", "1"];

  • map vale il suo primo operando a ogni elemento del suo secondo operando (["192", "168", "0", "1"] =>[192, 168, 0, 1]);

  • reduce prende i primi due argomenti dall'elenco e applica loro gli lambda; poi lo fa di nuovo con il risultato della lambda e il prossimo elemento della lista; e così via.

  • la funzione labmda (una funzione anonima definita sul posto) esegue questa operazione: prende il primo argomento, lo sposta di otto bit e OR in esso il nuovo blocco; così, ciò che accade è che il risultato è calcolato come:

    (((192<<8 | 168) << 8 | 0)<<8 | 1) = 192<<24 | 168<<16 | 0<<8 | 1 
    

    che è esattamente ciò che il "modulo tratteggiata" rappresenta (è solo una scorciatoia per indicare un numero intero senza segno a 32 bit, che è ciò che un IP in IPv4 - si potrebbe dire che è un po 'come esprimerla nella base di 256)

+0

Grazie mille. Ho capito il codice. Mi chiedo solo come implementare una funzione per convertire una stringa da intero a IP in questo modo? – zfz

5

| è un bitwise, logical or:

>>> 0 | 1 
1 
>>> 1 | 1 
1 

Ridurre chiamate il lambda con il totale di funzionamento corrente e il valore successivo (integer) dell'uscita della funzione map(). Quindi, si sta facendo quanto segue in un ciclo:

sum = 0 
for chunk in map(int, ip.split(".")): 
    sum = (sum << 8) | chunk 

dove map(int, ip.split(".")) trasformato l'indirizzo IP in una sequenza di numeri interi; 1.2.3.4 diventa [1, 2, 3, 4].

Il << è un bitwise left shift, da 8 bit in questo caso:

>>> 1 << 8 
256 

Quindi, per ciascuna parte intera di un indirizzo IP, esso sposta il valore a sinistra di 8 posizioni, e aggiunge i bit della prossima parte dell'indirizzo a quel numero.

Questo ha perfettamente senso, poiché un indirizzo IP non è altro che un numero a 32 bit e la notazione di stringa divide quel numero in 4 blocchi di 8 bit e "stampa" il valore intero di ciascuno di questi 8 bit con un carattere . in mezzo.

aiuta a stampare ogni fase come numero binario:

>>> map(int, '1.2.3.4'.split('.')) 
[1, 2, 3, 4] 
>>> bin(1) 
'0b1' 
>>> bin(2) 
'0b10' 
>>> bin(3) 
'0b11' 
>>> bin(4) 
'0b100' 
>>> bin(1 << 8) 
'0b100000000' 
>>> bin(1 << 8 | 2) 
'0b100000010' 
>>> bin((1 << 8 | 2) << 8) 
'0b10000001000000000' 
>>> bin((1 << 8 | 2) << 8 | 3) 
'0b10000001000000011' 
>>> bin(((1 << 8 | 2) << 8 | 3) << 8) 
'0b1000000100000001100000000' 
>>> bin(((1 << 8 | 2) << 8 | 3) << 8 | 4) 
'0b1000000100000001100000100' 
Problemi correlati