2010-04-04 2 views

risposta

71

Nello spirito Python di "chiedere perdono, non è permesso", Ecco un modo:

try: 
    b = a[4] 
except IndexError: 
    b = 'sss' 
+14

in modo semplice ?? – zjm1126

+2

Se si desidera una copertina singola, inserirla in una piccola funzione di supporto. –

+7

@zjm: questo * è * un modo semplice –

3
try: 
    b = a[4] 
except IndexError: 
    b = 'sss' 

un modo più pulito (funziona solo se si sta utilizzando un dict):

b = a.get(4,"sss") # exact same thing as above 

Ecco un altro modo, come si potrebbe (ancora una volta, solo per dicts):

b = a.setdefault(4,"sss") # if a[4] exists, returns that, otherwise sets a[4] to "sss" and returns "sss" 
+0

È necessario definire l'eccezione per "tranne:'. Ad esempio, la tua eccezione viene attivata anche quando la variabile 'a' non è definita. – zoli2k

+0

@Goose: empty 'except' è il male. È molto meglio dire "ad eccezione di IndexError" –

+0

@shakov, @Eli Bendersky: hai ragione. Fisso. –

0

Utilizzare try/catch?

try: 
    b=a[4] 
except IndexError: 
    b='sss' 
50

Nello spirito non-Python di "chiedere il permesso, non perdono", ecco un altro modo:

b = a[4] if len(a) > 4 else 'sss' 
+1

lo stava usando, bello vedere l'affidabilità confermata. Tendo ad evitare di provare (e ad afferrare) il più possibile. –

6

Si potrebbe anche definire una funzione di supporto poco per questi casi:

def default(x, e, y): 
    try: 
     return x() 
    except e: 
     return y 

Restituisce il valore restituito della funzione x, a meno che non abbia generato un'eccezione di tipo e; in tal caso, restituisce il valore . Uso:

b = default(lambda: a[4], IndexError, 'sss') 

Edit: Ha reso prendere solo un determinato tipo di eccezione.

I suggerimenti per il miglioramento sono ancora benvenuti!

+2

@Thomas: IMHO è inelegante, e l'allettante 'except' è preoccupante –

+1

C'è una discussione sulla mailing list su un costrutto come questo: http://mail.python.org/pipermail/python-dev/2009- Agosto/091039.html – Thomas

+0

Vecchia risposta, ma ancora. Python è una delle poche lingue in cui le eccezioni sono viste come una buona cosa. Viene spesso utilizzato per il controllo del flusso in cui crea la leggibilità. – Etse

1

Sono tutto per chiedere il permesso (ad esempio, non mi piace il metodo try ... except). Tuttavia, il codice diventa molto più pulito quando è incapsulato in un metodo:

def get_at(array, index, default): 
    if index < 0: index += len(array) 
    if index < 0: raise IndexError('list index out of range') 
    return array[index] if index < len(a) else default 

b = get_at(a, 4, 'sss') 
+2

'mylist [-1]' dovrebbe solo ottenere l'ultimo elemento, ma il tuo "permesso di richiesta" 'get_at' codice _doesn't_ si comporta in questo modo. Questo mostra uno dei tanti motivi per cui "chiedere il permesso" è solo la filosofia sbagliata: quello che stai verificando potrebbe non corrispondere a quello che il sistema farebbe. Ad esempio, non solo stai sistematicamente cercando di duplicare il lavoro che il sistema fa per te, ma puoi facilmente ottenere quel lavoro extra duplicato sbagliato. "chiedere perdono" è ** molto ** migliore. –

+0

@Alex: buona presa, non ci ho pensato. La sintassi delle porzioni di liste poweful di Python rende questo leggermente più complicato ... * tuttavia *, non sono d'accordo con la tua estrapolazione da questo caso speciale che "chiedere perdono" in generale è buono. Sono ovviamente di parte perché sono un grande sostenitore della tipizzazione statica. Ma comunque, questa è solo la conclusione sbagliata. Una conclusione migliore sarebbe che la mia analisi dei requisiti era insufficiente (* e * forse non c'è un buon modo per ottenere il comportamento interno in modo modificabile senza la duplicazione del codice o l'attivazione dell'errore.) Che punta a un'API errata. –

+0

Si può farla franca se si esegue 'def get_at (array, index, default): try: return array [index] tranne IndexError: return default' – voyager

0

Dal momento che questo è un top google successo, è probabilmente anche la pena ricordare che il pacchetto "collezioni" standard, ha un "defaultdict", che fornisce un soluzione più flessibile a questo problema.

Si possono fare cose ordinate, per esempio:

twodee = collections.defaultdict(dict) 
twodee["the horizontal"]["the vertical"] = "we control" 

Per saperne di più: http://docs.python.org/2/library/collections.html

11

Si potrebbe creare la tua selezione di classe:

class MyList(list): 
    def get(self, index, default=None): 
     return self[index] if len(self) > index else default 

è possibile utilizzarlo come questo :

>>> l = MyList(['a', 'b', 'c']) 
>>> l.get(1) 
'b' 
>>> l.get(9, 'no') 
'no' 
1

Per un caso comune in cui si desidera che il primo elemento, si può fare

next(iter([1, 2, 3]), None) 

Io lo uso per "scartare" una lista, eventualmente dopo filtraggio.

next((x for x in [1, 3, 5] if x % 2 == 0), None) 

o

cur.execute("SELECT field FROM table") 
next(cur.fetchone(), None) 
15

Nello spirito Python di bello è meglio di brutto metodo Codice golf

, utilizzando fetta e disimballaggio

b=a[4:4+1] or 'sss' 

più bello di una funzione wrapper o prova a prendere IMHO, ma intimidatorio per i principianti. Personalmente trovo tuple disfacendo essere il modo più sexy di lista [#]

utilizzando affettare senza disimballare:

b,=a[4:5] or ['sss'] 

o, se si ha a che fare questo, spesso, e non vi dispiace fare un dizionario

d = dict(enumerate(a)) 
b=d.get(4,'sss') 
+1

Il tuo primo esempio non funziona se l'elenco è più lungo di 5 elementi. E andare con 'a [4: 5]' non è più bello ... –

+0

'usare lo splicing senza decomprimere' è ciò che funziona per me, altrimenti l'elemento restituito era un elenco di dimensioni 1, non uno scalare. –

+0

Perché la prima risposta contiene virgole aggiuntive? Interpretare nell'interprete python: 'b, = a [4:] o 'sss',' è uguale a 'b = a [4:] o 'sss'' –

9

un altro modo:

b = (a[4:]+['sss'])[0] 
+0

Ok, quindi mi piace la mancanza di verbosità. Potresti spiegare un po 'la sintassi? – froggythefrog

+0

'a [4:]' crea un elenco di elementi, da (incluso) indice 4. Ne risulta un elenco vuoto. '[1, 2, 3] [999:] == []' È come funziona l'operazione di taglio. Se 'a' fosse' ['123', '2', 4, 5, 6] ', ritornerebbe [5, 6]. Quindi aggiunge l'elemento 'sss', creando una nuova lista, che è '['sss']' in questo caso. Il passo finale '[0]' prende solo il primo elemento, restituendo così '' sss'', ma restituire 'a [4]' se ci fosse un tale elemento' –

+0

un modo interessante per ottenere questo. un po 'sul lato illeggibile. – Alex

0

Se siete alla ricerca di un modo mantenibile di ottenere valori di default sull'operatore indice ho trovato il seguente utile:

Se si sostituisce operator.getitem dal modulo operatore per aggiungere un parametro predefinito facoltativo si ottiene un comportamento identico all'originale pur mantenendo la compatibilità all'indietro.

0

Se si sta cercando un trucco rapido per ridurre la lunghezza del codice in senso stretto, è possibile provare questo.

a=['123','2',4] 
a.append('sss') #Default value 
n=5 #Index you want to access 
max_index=len(a)-1 
b=a[min(max_index, n)] 
print(b) 

Ma questo trucco è utile solo quando non si desidera più ulteriori modifiche alla lista