2010-10-12 8 views

Respuesta

72

se crea una rebanada llamando rebanada con los mismos campos que usaría si al hacerlo [Inicio: Fin: paso] notación:

sl = slice(0,4) 

Para utilizar la rebanada, sólo tiene que pasar como si fuera el índice en una lista o cadena:

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

Digamos que tiene un archivo de campos de texto de longitud fija. Podría definir una lista de sectores para extraer fácilmente los valores de cada "registro" en este archivo.

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('') 

Prints:

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 función slice devuelve slice objects. Los objetos Slice son uno de los tipos internos de Python, que están optimizados para el rendimiento de lectura: todos sus atributos son de solo lectura.

Alterar slice podría ser útil si desea cambiar el comportamiento predeterminado. Por ejemplo, lxml usa notación de división para acceder a los elementos DOM (sin embargo, no he confirmado cómo lo hicieron yo).

28

corchetes siguientes una secuencia denotan cualquiera de indexación o rebanado dependiendo de lo que está dentro de los corchetes:

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

Ambos de estos casos son manejados por el método __getitem__() de la secuencia (o __setitem__() si está a la izquierda de un signo igual.) El índice o sector se pasa a los métodos como un único argumento, y t La forma en que Python lo hace es convirtiendo la notación de división, (1:10:2, en este caso) en un objeto de división: slice(1,10,2).

Así que si va a definir su propia secuencia de la clase similar o anulando las __getitem__ o __setitem__ o __delitem__ métodos de otra clase, es necesario poner a prueba el argumento índice para determinar si es un int o una slice, y el proceso en consecuencia:

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 objeto slice tiene tres atributos: start, stop y step, y un método: indices, que toma un solo argumento, la longitud del objeto, y devuelve un 3-tupla: (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

Consulte la respuesta de Don a continuación para obtener una explicación de por qué sucede esto. – abc

+0

Sería beneficioso también señalar que puede haber varias divisiones pasadas a '__getitem__':' s [1: 2: 3, 1, 4: 5] => (slice (1, 2, 3), 1 , slice (4, 5, None)) '. – OozeMeister

Cuestiones relacionadas