2009-03-25 7 views
5

Je voudrais créer un objet tranche à partir d'une chaîne; en ce moment le seul moyen semble par une déclaration eval hacky lourdepython créer un objet tranche à partir de la chaîne

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

merci à l'avance.

Édition: Désolé si l'invite d'origine n'était pas claire, l'entrée dans ce cas était ": -1". Le but était d'analyser la chaîne. La réponse d'Ignacio Vazquez-Abrams a au moins résolu le problème (et semble aussi fonctionner avec l'indexation inversée), mais je pense que ma solution ci-dessus est encore plus claire sinon conceptuelle (et fonctionnera correctement si Python change la syntaxe de découpage).

+0

Pouvez-vous être un peu plus clair sur quel comportement vous recherchez? –

+0

-1: Pourquoi créer un objet tranche autonome? Les tranches sont des morceaux de syntaxe de première classe? Sans aucune raison de savoir pourquoi vous feriez cela, la question est très étrange. –

+0

Jaffe: question mise à jour. Lott: Je fais un peu de travail de langage, et je voudrais aussi utiliser des tranches Python. L'objet réel est très utile: il a une fonction indices (len) qui donnera un (start, stop, increment) donné une longueur de tableau – gatoatigrado

Répondre

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

c'est un peu faux, e. g. '1: 1: 1: 1' n'est pas une chaîne de tranche correcte et '1: 1: 1' l'est. Devrait plus quelque chose comme ceci: tranche (* carte (lambda x: int (x.strip()) si x.strip() sinon Aucun, mystring.split (':'))) – pprzemek

+3

Plus c'est du code vraiment moche. – Evpok

+1

pprzemek, votre commentaire contient la meilleure réponse à mon avis, pourquoi n'en faites-vous pas une vraie réponse? –

4

Si vous voulez un objet tranche, pourquoi ne pas simplement instancier un?

s = slice(start, stop, step) 

Que voulez-vous dire par "le créer à partir d'une chaîne"?

0

Un objet tranche est généralement créé en utilisant la notation en indice, cette notation utilise slice() en interne, comme indiqué sur le slice() documentation. Qu'est-ce que vous voulez faire est:

your_string[start:end] 

De the python tutorial:

Les chaînes peuvent être indicés (indexés); Comme dans C, le premier caractère d'une chaîne a l'indice (index) 0. Il n'y a aucun type de caractère séparé; un caractère est simplement une chaîne de taille un. Comme dans Icon, les sous-chaînes peuvent être spécifiées avec la notation de tranche: deux index séparés par deux points.

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

indices ont Slice par défaut utiles; un omis premier index par défaut à zéro, un deuxième index omis par défaut à la taille de la chaîne en cours de tranchage.

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

désolé, ce n'est pas ce que je demandais, je veux analyser la tranche, par exemple. "-3 :: 2" à partir d'une chaîne, et retourne un objet slice [voir la question initiale]. – gatoatigrado

+0

Il ne ressort pas clairement de votre question que c'est ce que vous demandiez. Je suis désolé de ne pouvoir plus vous aider, ce que je vous recommande est de lire le Zen de Python et de reconsidérer si ce que vous essayez de faire ne va pas à l'encontre, si c'est le cas, c'est probablement une mauvaise idée. – mpeterson

+0

bien sûr, je pense que la plupart de mon code répond à cela (merci pour le ref). Je suis désolé, je ne sais pas comment clarifier plus; Avez-vous lu la question révisée (et les commentaires ci-dessous)? salutations, Nicholas – gatoatigrado

1

Je finis ici parce que je voulais que mon script pour accepter un argument épissage comme python et le rendre dans une liste d'entiers, je l'ai fait avec une fonction qui semble comme il répond à la la question de l'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) 

sortie:

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

Basé sur @pprzema k rédigé la fonction suivante pour l'analyse élaborée:

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

Voici une autre méthode (juste une consolidation des autres affichés ici):

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) 

Exemples d'utilisation:

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] 
Questions connexes