2009-03-25 14 views
5

Mi piacerebbe creare un oggetto fetta da una stringa; in questo momento l'unica via sembra attraverso una ingombrante dichiarazione di evasione hackypython crea oggetto fetta da stringa

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

grazie in anticipo.

Modifica: Scusa se il prompt originale non era chiaro, l'input in questo caso era ": -1". Il punto era analizzare la stringa. La risposta di Ignacio Vazquez-Abrams ha risolto almeno il problema (e sembra funzionare anche con l'indicizzazione inversa), ma penso che la mia soluzione sopra sia ancora più chiara se non concettualmente pulita (e funzionerà correttamente se Python cambierà mai la sintassi di slicing).

+0

Può essere un un po 'più chiaro su quale comportamento stai cercando? –

+0

-1: Perché dovresti creare un oggetto fetta autonomo? Le fette sono pezzi di sintassi di prima classe? Senza alcuna base sul perché lo farei, la domanda è molto strana. –

+0

Jaffe: domanda aggiornata. Lott: Sto facendo un po 'di lavoro sul linguaggio e vorrei usare anche le sezioni di Python. L'oggetto reale è piuttosto utile: ha una funzione di indici (len) che darà un (inizio, fine, incremento) data una lunghezza dell'array – gatoatigrado

risposta

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

questo è un po 'sbagliato, e. g. '1: 1: 1: 1' non è una stringa di sezione corretta e '1: 1: 1' è. Più qualcosa di simile: slice (* map (lambda x: int (x.strip()) se x.strip() else None, mystring.split (':'))) – pprzemek

+3

Inoltre è un codice davvero brutto. – Evpok

+1

pprzemek, il tuo commento contiene la risposta migliore a mio parere, perché non ne fai una vera risposta? –

4

Se si desidera un oggetto fetta, perché non basta istanziarne uno?

s = slice(start, stop, step) 

Che cosa intendi per "creare da una stringa"?

0

Un oggetto porzione viene in genere creato utilizzando la notazione degli indici, questa notazione utilizza slice() internamente, come indicato nello slice() documentation. Che cosa si vuole fare è:

your_string[start:end] 

Da the python tutorial:

stringhe possono essere in pedice (indicizzati); come in C, il primo carattere di una stringa ha indice (indice) 0. Ci non è un tipo di carattere separato; un carattere è semplicemente una stringa di dimensioni uno. Come in Icon, le sottostringhe possono essere specificate con la notazione di sezione: due indici separati da due punti.

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

indici delle fette sono predefiniti utili; un omesso primo indice predefinito su zero, un secondo indice omesso predefinito su la dimensione della stringa che viene tagliata.

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

scusa, non è quello che stavo chiedendo, voglio analizzare la fetta, ad es. "-3: 2" da una stringa e restituisce un oggetto porzione [vedi domanda originale]. – gatoatigrado

+0

Non è chiaro dalla tua domanda che è quello che stavi chiedendo. Mi dispiace di non poterti più aiutare, quello che ti consiglio comunque è di leggere lo Zen di Python e riconsiderare se ciò che stai cercando di fare non va contro di esso, se lo fa è probabilmente una cattiva idea. – mpeterson

+0

certo, penso che la maggior parte del mio codice soddisfi questo (grazie per l'arbitro). Mi dispiace, non so come chiarire di più; hai letto la domanda rivista (e commenti sotto)? saluti, Nicholas – gatoatigrado

1

finisco qui perché volevo il mio script per accettare un argomento giunzione python-like e renderlo in un elenco di numeri interi, l'ho fatto con una funzione che sembra come esso risponde alla domanda di 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) 

uscita:

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

sulla base di @pprzema k ha redatto la seguente funzione per l'analisi elaborata:

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

Ecco un altro metodo (solo un consolidamento delle altre postato qui):

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) 

Esempio usi:

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]