Esempi concreti della massima "solo un modo per farlo" di Python [chiuso]


34

Sto imparando Python e sono incuriosito dal seguente punto in PEP 20 The Zen of Python :

Dovrebbe esserci uno - e preferibilmente solo un - modo obsoleto di farlo. Anche se in quel modo all'inizio potrebbe non essere ovvio a meno che tu non sia olandese.

Qualcuno potrebbe offrire qualche esempio concreto di questa massima? Sono particolarmente interessato al contrasto con altre lingue come Ruby. Parte della filosofia del design di Ruby (originata da Perl, penso?) È che molteplici modi di farlo è A Good Thing. Qualcuno può offrire alcuni esempi che mostrano i pro ei contro di ogni approccio. Nota, non sto cercando una risposta alla quale è meglio (che è probabilmente troppo soggettiva per mai avere una risposta), ma piuttosto un confronto imparziale dei due stili.

Risposte:


47

Rispetto a linguaggi come Perl, Python ha un numero limitato di costrutti di controllo:

  • solo ife no unless,
  • solo forche scorre su sequenze e no foreacho stile C for,
  • solo whileche controlla una condizione ogni ciclo e no do-while,
  • solo if-elife no switch,
  • c'è solo un costrutto di commento, il #, e per ogni riga che puoi dire se è commentato o meno, senza guardare le righe precedenti.

Inoltre, c'è quasi un modo per indentare la tua fonte; la maggior parte dei casi di rientro creativo sono sintatticamente esclusi.

Questo rende l'analisi di una fonte Python più facile per l'uomo.

Ci sono tentativi di essere minimi ma completi nei tipi predefiniti e nella libreria standard.

  • per la lista mutabile usi l'unico tipo incorporato list; è O (1) per la maggior parte delle operazioni e non devi mai scegliere l'implementazione giusta,
  • per gli elenchi immutabili, allo stesso modo, basta usare il tupletipo,
  • per le mappe, usi l'unico built-in dictche è dannatamente efficiente nella maggior parte dei casi, non è necessario ponderare quale implementazione utilizzare.

Python 3 estende questo a numeri interi: non importa quanto sia grande il tuo numero intero, usi lo stesso tipo e non ti preoccupi mai della coercizione.

Python cerca di evitare lo zucchero sintattico. Ma a volte aggiunge zucchero sintattico solo per rendere ovvio il modo ovvio. Puoi scrivere if foo is not Noneinvece che if not (foo is None)perché "non è" è in maiuscolo. foo is not NoneLegge ancora facilmente, non può essere frainteso, e non devi pensare, scrivi semplicemente la cosa ovvia.

Naturalmente, la maggior parte delle cose più complesse in Python può essere eseguita in diversi modi. È possibile aggiungere metodi alle classi mediante dichiarazione o assegnazione di uno slot semplice, è possibile passare argomenti a funzioni in diversi modi creativi, ecc. Questo è solo perché gli interni della lingua sono esposti per lo più.

La chiave è che c'è sempre un modo che è destinato a essere il migliore, il caso di copertura generale. Se esistono altri modi, non sono stati aggiunti come alternative uguali (come ife unless) ma semplicemente espongono il funzionamento interno. Lentamente ma costantemente tali alternative sono obsolete (non eliminate!) Migliorando il meccanismo migliore noto.

I decoratori avvolgono le chiamate di funzione AOP. Prima del 2.6 dovevi usare __metaclass__un membro magico per dichiarare la metaclasse di una classe; ora puoi usare la stessa sintassi di decoratore anche per questo. Prima della 3.0 avevi due tipi di stringhe, orientate ai byte e Unicode, che potresti inavvertitamente mescolare. Ora hai l'unico Unicode stre l'unico binario-trasparente bytes, che non puoi mescolare per errore.


3
Proprio come una nota, non dimenticare i """commenti (docstrings). Questi si estendono su più righe.
asthasr

8
I letterali a tre virgolette sono solo stringhe, le stesse di virgolette singole, ma possono estendersi su più righe senza sfuggire alle estremità delle righe. Una stringa letterale subito dopo la dichiarazione è considerata una stringa doc e non è un commento, di solito è accessibile come __doc__attributo. Ma le stringhe sono un'area in cui Python offre sicuramente molti "modi giusti": usa virgolette singole, doppie o triple, unisci implicitamente valori letterali adiacenti, usa rvalori letterali grezzi, ecc.
9000

1
Penso che il commento di @ syrion riguardasse il "puoi sempre decidere se una riga è commentata o meno semplicemente guardandola", il che non è vero a causa delle "" "stringhe.
blubb

2
"Questo rende l'analisi di una fonte Python più facile per gli umani." <- Questo è soggettivo
jiggy,

Come è cambiata la dichiarazione della metaclasse in 2.7? Non è possibile trovare il modello di decorazione nei documenti 2.7 per metaclassi.
Nick T,

10

Un'altra coppia di esempi sono:
len()è una funzione anziché un metodo presente in ogni sequenza; se si confronta con Java si dispone .length, .size(), .getSize()e altri metodi per trovare il numero di elementi in una sequenza.

Un altro esempio è il fatto che .join()è astring metodo, non un metodo presente in ogni sequenza. Non è necessario sapere se il parametro join è un elenco, un set, una comprensione o qualsiasi altra cosa funzionerà.


8

In C ci sono molti modi possibili per aumentare il valore di una variabile di uno:

i++     // Post-increment, returns the number before the increment
++i     // Pre-increment, returns the number after the increment
i += 1 

Ognuno finisce per aumentare il valore di idi 1, ma ognuno è leggermente diverso.

In Python, c'è davvero solo un modo; basta aggiungerne uno.

i += 1

E mentre c'è più di un modo sintatticamente valido per farlo (ad esempio i = i + 1), stai facendo la stessa cosa con gli stessi effetti collaterali.


1
Non sono un esperto, ma quell'esempio sembra violare con precisione l'idea "un solo modo per farlo". Abbiamo due modi per farlo, ma qual è il più ovvio? A mio avviso, il primo esempio è più ovvio mentre il secondo è un po 'più conciso ma non meno leggibile o ovvio per qualsiasi programmatore che ha progredito oltre le basi. Grazie per la risposta: è un buon spunto di riflessione.
Charles Roper,

@Peter (e @Charles): In realtà, i = i + 1è un compito, non un incremento. In Python c'è un incremento i += 1. In linguaggi in stile C è possibile scrivere i++, ++ie i += 1.
Josh K,

2
Non sono sicuro del tuo commento "molta confusione", tutti e tre i tuoi esempi in C (ti sei perso i += 1, BTW) producono esattamente lo stesso risultato. L'unica volta in cui vedo le persone confuse è quando pre-incrementano o post-incrementano una variabile come parte di un'espressione più ampia, e questo di solito viene rapidamente corretto leggendo l'apposita sezione del riferimento linguistico. Personalmente, avrei scelto il fatto che puoi fare riferimento al quinto carattere di una stringa da entrambi str[4]o *(str+4), ma forse è stato troppo facile ...
TMN

2
@TMN: alcuni casi, ad esempio max(i++, ++i)non possono essere corretti rapidamente. C ha molti casi comportamentali "non definiti" e "dipendenti dall'implementazione", tutti per una buona ragione, ma ognuno di essi può creare una trappola.
9000,

@TMN: per non parlare di 4 [str] (valido in C, potrebbe non essere valido in C ++).
Vatine,

6

Un'altra possibilità potrebbe essere la comprensione dell'elenco. In Python, si potrebbe fare questo:

new_list = []
    for item in list_of_items:
       if item < 10:
           new_list.append(item)

Ma il modo "ovvio" (se sei olandese o hai più familiarità con Python) di farlo sarebbe con una comprensione della lista:

new_list = [item for item in list_of_items if item < 10]

È più corto, la new_list viene creata in un solo passaggio, credo che funzioni più veloce ed è elegante. Il rovescio della medaglia, si potrebbe sostenere che sembra meno esplicito, ma penso che una volta che ci si abitua, è altrettanto esplicito.


Per rientro e codice: anteponilo di 4 spazi, quindi rispetterà il rientro.
Inca,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.