2010-10-12 9 views

risposta

72

si crea una fetta chiamando fetta con gli stessi campi si userebbe se facendo [start: end: step] notazione:

sl = slice(0,4) 

Per utilizzare la fetta, basta passare come se fosse l'indice in una lista o stringa:

>>> s = "ABCDEFGHIJKL" 
>>> sl = slice(0,4) 
>>> print(s[sl]) 
'ABCD' 

Supponiamo di avere un file di campi di testo a lunghezza fissa. È possibile definire un elenco di sezioni per estrarre facilmente i valori da ciascun "record" in questo file.

data = """\ 
0010GEORGE JETSON 12345 SPACESHIP ST HOUSTON  TX 
0020WILE E COYOTE 312 ACME BLVD  TUCSON  AZ 
0030FRED FLINTSTONE 246 GRANITE LANE  BEDROCK  CA 
0040JONNY QUEST  31416 SCIENCE AVE PALO ALTO  CA""".splitlines() 


fieldslices = [slice(*fielddef) for fielddef in [ 
    (0,4), (4, 21), (21,42), (42,56), (56,58), 
    ]] 
fields = "id name address city state".split() 

for rec in data: 
    for field,sl in zip(fields, fieldslices): 
     print("{} : {}".format(field, rec[sl])) 
    print('') 

stampe:

id : 0010 
name : GEORGE JETSON  
address : 12345 SPACESHIP ST 
city : HOUSTON  
state : TX 

id : 0020 
name : WILE E COYOTE  
address : 312 ACME BLVD   
city : TUCSON   
state : AZ 

id : 0030 
name : FRED FLINTSTONE 
address : 246 GRANITE LANE  
city : BEDROCK  
state : CA 

id : 0040 
name : JONNY QUEST  
address : 31416 SCIENCE AVE  
city : PALO ALTO  
state : CA 
3

La funzione slice restituisce slice objects. Gli oggetti slice sono uno dei tipi interni di Python, che sono ottimizzati per le prestazioni di lettura - tutti i loro attributi sono di sola lettura.

Altering slice potrebbe essere utile se si desidera modificare il comportamento predefinito. Ad esempio, lxml utilizza la notazione di sezione per accedere agli elementi DOM (tuttavia, non ho confermato come l'hanno fatto personalmente).

28

parentesi quadre seguendo una sequenza indicano sia indicizzazione o affettamento seconda di ciò che è all'interno delle parentesi:

>>> "Python rocks"[1] # index 
'y' 
>>> "Python rocks"[1:10:2] # slice 
'yhnrc' 

Entrambi questi casi sono gestite dai il metodo __getitem__() della sequenza (o __setitem__() se sulla sinistra di un segno di uguale). L'indice o la sezione viene passato ai metodi come un singolo argomento, e t Il modo in cui lo fa Python è convertendo la notazione della sezione, (1:10:2, in questo caso) in un oggetto porzione: slice(1,10,2).

Quindi, se si sta definendo la propria classe di sequenza simile o ignorando le __getitem__ o __setitem__ o __delitem__ metodi di un'altra classe, è necessario testare l'argomento indice per determinare se si tratta di un int o un slice, e il processo di conseguenza:

def __getitem__(self, index): 
    if isinstance(index, int): 
     ... # process index as an integer 
    elif isinstance(index, slice): 
     start, stop, step = index.indices(len(self)) # index is a slice 
     ... # process slice 
    else: 
     raise TypeError("index must be int or slice") 

un oggetto slice ha tre attributi: start, stop e step, e un metodo: indices, che prende un singolo argomento, la lunghezza dell'oggetto, e restituisce una tupla di 3 elementi: (start, stop, step).

5
>>> class sl: 
... def __getitem__(self, *keys): print keys 
...  
>>> s = sl() 
>>> s[1:3:5] 
(slice(1, 3, 5),) 
>>> s[1:2:3, 1, 4:5] 
((slice(1, 2, 3), 1, slice(4, 5, None)),) 
>>> 
+2

Vedere la risposta di Don qui sotto per spiegazioni sul perché questo accade. – abc

+0

Sarebbe utile sottolineare anche che possono essere passate più fette in '__getitem__':' s [1: 2: 3, 1, 4: 5] => (slice (1, 2, 3), 1 , slice (4, 5, None)) '. – OozeMeister

Problemi correlati