2009-03-25 24 views
5

Me gustaría crear un objeto slice a partir de una cadena; en este momento la única forma parece a través de una incómoda declaración eval hackypython create slice object desde la cadena

class getslice: 
    def __getitem__(self, idx): return idx[0] 
eval("getslice()[%s, 1]" %(":-1")) 

gracias de antemano.

Editar: Disculpe si el mensaje original no era claro, la entrada en este caso era ": -1". El punto era analizar la cadena. La respuesta de Ignacio Vazquez-Abrams al menos resolvió el problema (y parece funcionar también con la indexación inversa), pero creo que mi solución anterior es más clara si no es conceptualmente limpia (y funcionará correctamente si Python alguna vez cambia la sintaxis de corte).

+0

¿Puede ser una un poco más claro sobre qué comportamiento estás buscando? –

+0

-1: ¿Por qué crearías un objeto de división independiente? Las rebanadas son piezas de sintaxis de primera clase? Sin ningún conocimiento sobre por qué harías esto, la pregunta es muy extraña. –

+0

Jaffe: pregunta actualizada. Lott: Estoy haciendo un poco de trabajo de lenguaje, y me gustaría usar las partes de Python también. El objeto real es bastante útil: tiene una función de índices (len) que dará un (inicio, parada, incremento) dada una longitud de matriz – gatoatigrado

Respuesta

3
slice(*[{True: lambda n: None, False: int}[x == ''](x) for x in (mystring.split(':') + ['', '', ''])[:3]]) 
+7

esto es un poco incorrecto, e. gramo. '1: 1: 1: 1' no es una cadena de corte correcta y '1: 1: 1' es. Debería haber algo más como esto: slice (* map (lambda x: int (x.strip()) si x.strip() else Ninguno, mystring.split (':'))) – pprzemek

+3

Además, es realmente un código feo. – Evpok

+1

pprzemek, su comentario contiene la mejor respuesta en mi opinión, ¿por qué no hace una verdadera respuesta? –

4

Si desea un objeto de sector, ¿por qué no hace una instancia de uno?

s = slice(start, stop, step) 

¿Qué estás queriendo decir con "creándolo de una cadena"?

0

Un objeto de división se suele crear con notación de subíndice, esta notación utiliza slice() internamente, como se indica en slice() documentation. Lo que se quiere hacer es:

your_string[start:end] 

De the python tutorial:

cadenas tienen subíndices (indexados); como en C, el primer carácter de una cadena tiene subíndice (índice) 0. No no es un tipo de carácter separado; un carácter es simplemente una cadena de tamaño uno. Al igual que en Icon, las subcadenas pueden ser especificadas con la notación slice: dos índices separados por dos puntos.

>>> word = 'Help' + 'A' 
>>> word[4] 
'A' 
>>> word[0:2] 
'He' 
>>> word[2:4] 
'lp' 

índices Slice tienen valores predeterminados útiles; un primer índice omitido está predeterminado a cero, un segundo índice omitido está predeterminado en el tamaño de la cadena que se corta.

>>> word[:2] # The first two characters 
'He' 
>>> word[2:] # Everything except the first two characters 
'lpA' 
+0

lo siento, eso no es lo que estaba preguntando, quiero analizar el sector, p. "-3 :: 2" de una cadena, y devuelve un objeto de división [ver la pregunta original]. – gatoatigrado

+0

No está claro por su pregunta que eso es lo que estaba preguntando. Lamento no poder ayudarte más, pero lo que te recomiendo es leer el Zen de Python y reconsiderar si lo que intentas hacer no va en contra de eso, si es así, probablemente sea una mala idea. – mpeterson

+0

seguro, creo que la mayoría de mi código cumple con eso (gracias por la referencia). Lo siento, no sé cómo aclarar más; ¿Leíste la pregunta revisada (y los comentarios a continuación)? respetos, Nicholas – gatoatigrado

1

llegué aquí porque quería que mi script para aceptar un argumento de empalme pitón similar y lo hacen en una lista de números enteros, lo hice con una función que parece que responde a la la pregunta de OP:

# create a slice object from a string 
def get_slice_obj(slicearg): 
    slice_ints = tuple([ int(n) for n in slicearg.split(':') ]) 
    return apply(slice, slice_ints) 

def ints_from_slicearg(slicearg): 
    slice_obj = get_slice_obj(slicearg) 
    return(range(slice_obj.start or 0, slice_obj.stop or -1, slice_obj.step or 1)) 

for t in ['1', '1:3', '4:9:2']: 
    print t, "=>", ints_from_slicearg(t) 

salida:

1 => [0] 
1:3 => [1, 2] 
4:9:2 => [4, 6, 8] 
0

Basado en @pprzema k redactó la siguiente función para elaborar análisis:

def parse_slice(v: Text): 
    """ 
    Parses text like python "slice" expression (ie ``-10::2``). 

    :param v: 
     the slice expression or a lone integer 
    :return: 
     - None if input is None/empty 
     - a ``slice()`` instance (even if input a lone numbrt) 
    :raise ValueError: 
     input non-empty but invalid syntax 
    """ 
    orig_v = v 
    v = v and v.strip() 
    if not v: 
     return 

    try: 
     if ':' not in v: 
      ## A lone number given. 
      v = int(v) 
      return slice(v, v + 1) 

     return slice(*map(lambda x: int(x.strip()) if x.strip() else None, 
          v.split(':'))) 
    except Exception: 
     pass 

    ## An alternative is to return `slice(None)` here. 
    raise trt.TraitError("Syntax-error in '%s' slice!" % orig_v) 
0

Aquí hay otro método (sólo una consolidación de los demás publicada aquí):

def make_slice(expr): 
    def to_piece(s): 
     return s and int(s) or None 
    pieces = map(to_piece, expr.split(':')) 
    if len(pieces) == 1: 
     return slice(pieces[0], pieces[0] + 1) 
    else: 
     return slice(*pieces) 

Ejemplo usos:

In [1]: make_slice(':') 
Out[1]: slice(None, None, None) 

In [2]: make_slice(':-2') 
Out[2]: slice(None, -2, None) 

In [3]: x = [1, 2, 3] 

In [4]: x[make_slice('::-1')] 
Out[4]: [3, 2, 1]