Quali sono gli svantaggi di Python? [chiuso]


147

Python sembra essere di gran moda in questi giorni, e non immeritatamente, perché è davvero un linguaggio con il quale quasi si diverte a ricevere un nuovo problema da risolvere. Ma, come disse una volta un saggio (chiamandolo un saggio solo perché non ho idea di chi l'abbia effettivamente detto; non sono sicuro che fosse così saggio), conoscere davvero una lingua che non si conosce solo sintassi, design, ecc., vantaggi ma anche i suoi svantaggi. Nessuna lingua è perfetta, alcune sono semplicemente migliori di altre.

Quindi, quale sarebbe secondo te, gli svantaggi oggettivi di Python.

Nota: non sto chiedendo un confronto linguistico qui (cioè C # è meglio di Python perché ... yadda yadda yadda) - più di un'opinione oggettiva (ad un certo livello) quali caratteristiche del linguaggio sono mal progettate, se, quali sono forse alcuni ti manchi e così via. Se deve usare un'altra lingua come confronto, ma solo per illustrare un punto su cui sarebbe difficile elaborare altrimenti (cioè per facilità di comprensione)


50
Penso che questa sia una domanda soggettiva utile, e sarebbe un peccato chiuderla.
Eric Wilson,

25
Sembra che ci sia un fan-python qui che ha appena declassato tutte le risposte anti-pitone.
zvrba,

2
@TMN: Questo sta ancora trattando gli spazi bianchi come token, semplicemente non restituendoli - ed è esattamente ciò che fa anche la grammatica di Python.

9
@Roger: la convenzione su SO è di commentare i voti negativi. Dal momento che questo è un sito per opinioni soggettive , non vedo alcun motivo per i voti negativi, esp. senza commenti. Quindi, sostengo il mio "insulto".
zvrba,

8
@zvrba: downvotes significa ancora "non utile", come sempre.

Risposte:


109

Uso Python un po 'regolarmente, e nel complesso lo considero un linguaggio molto valido. Tuttavia, nessuna lingua è perfetta. Ecco gli svantaggi in ordine di importanza per me personalmente:

  1. È lento. Intendo davvero, molto lentamente. Molte volte questo non ha importanza, ma significa sicuramente che avrai bisogno di un'altra lingua per quei bit critici per le prestazioni.

  2. Le funzioni nidificate in qualche modo risucchiano dal fatto che non è possibile modificare le variabili nell'ambito esterno. Modifica: uso ancora Python 2 a causa del supporto della libreria e questo difetto di progettazione mi irrita, ma a quanto pare è stato risolto in Python 3 a causa dell'istruzione non locale . Non vedo l'ora che le librerie che uso vengano portate in modo che questo difetto possa essere inviato per sempre al cumulo di ceneri della storia.

  3. Manca alcune funzionalità che possono essere utili per la libreria / codice generico e IMHO sono semplicità portata agli estremi malsani. I più importanti che mi vengono in mente sono tipi di valore definiti dall'utente (suppongo che questi possano essere creati con la magia della metaclasse, ma non ho mai provato) e il parametro della funzione ref.

  4. È lontano dal metallo. Hai bisogno di scrivere threading primitive o codice del kernel o qualcosa del genere? In bocca al lupo.

  5. Sebbene non mi dispiaccia la mancanza di capacità di cogliere in anticipo errori semantici come un compromesso per il dinamismo offerto da Python, vorrei che ci fosse un modo per catturare errori sintattici e cose stupide come errori di digitazione dei nomi delle variabili senza dover eseguire effettivamente il codice.

  6. La documentazione non è buona come lingue come PHP e Java che hanno solide basi aziendali.


60
@ Casey, non sono d'accordo. L'indice è orribile: prova a cercare l' withaffermazione o i metodi su a list. Tutto ciò che è trattato nel tutorial è fondamentalmente non ricercabile. Ho molta più fortuna con la documentazione di Microsoft per C ++.
Mark Ransom,

17
Circa 5 - basta usare i pyflakes. È scritto per catturare esattamente quegli errori.
Alexander Solovyov,

4
Per quanto riguarda la velocità: con l'ascesa di PyPy, molti utenti Python saranno ora in grado di gestire il problema della velocità semplicemente usando un interprete con un compilatore JIT incorporato (per ora, gli utenti Python 3 e gli utenti dei moduli di estensione C non gestiti da cpyext non hai questa opzione).
ncoghlan,

29
Disprezzo i documenti di Python. Sono più carini della maggior parte per essere sicuri, ma molte volte molte informazioni utili sono raggruppate in una pagina, come i metodi su stringhe ed elenchi - e anche tutti i tipi di sequenza sono raggruppati insieme. Quando cerco queste informazioni, atterro su un enorme tomo e devo cercare in fondo alla pagina per trovare quello che voglio. Trovo anche l'indice su queste pagine difficile da leggere, ed è talvolta difficile dire quale sezione voglio.
Carson Myers,

5
In che modo la distanza dal metallo può essere un argomento? Python si è mai preteso di essere un linguaggio di sistema?
Mark Canlas,

66

Odio che Python non riesca a distinguere tra dichiarazione e utilizzo di una variabile. Non è necessario digitare staticamente per farlo accadere. Sarebbe bello avere un modo per dire "questa è una variabile che dichiaro deliberatamente e intendo introdurre un nuovo nome, questo non è un errore di battitura".

Inoltre, di solito uso le variabili Python in uno stile write-once, ovvero considero le variabili come immutabili e non le modifico dopo il loro primo incarico. Grazie a funzionalità come la comprensione dell'elenco, questo è incredibilmente facile e rende il flusso del codice più facile da seguire.

Tuttavia, non posso documentare questo fatto. Niente in Python mi impedisce di sovrascrivere o riutilizzare le variabili.

In sintesi, vorrei avere due parole chiave nella lingua: vare let. Se scrivo su una variabile non dichiarata da nessuno di questi, Python dovrebbe generare un errore. Inoltre, letdichiara le variabili di sola lettura, mentre le varvariabili sono "normali".

Considera questo esempio:

x = 42    # Error: Variable `x` undeclared

var x = 1 # OK: Declares `x` and assigns a value.
x = 42    # OK: `x` is declared and mutable.

var x = 2 # Error: Redeclaration of existing variable `x`

let y     # Error: Declaration of read-only variable `y` without value
let y = 5 # OK: Declares `y` as read-only and assigns a value.

y = 23    # Error: Variable `y` is read-only

Si noti che i tipi sono ancora impliciti (ma le letvariabili sono a tutti gli effetti tipizzate staticamente poiché non possono essere rimbalzate su un nuovo valore, mentre le varvariabili possono ancora essere tipizzate dinamicamente).

Infine, tutti gli argomenti del metodo dovrebbero essere automaticamente let, cioè dovrebbero essere di sola lettura. In generale, non esiste alcun motivo valido per modificare un parametro, ad eccezione del seguente linguaggio:

def foo(bar = None):
    if bar == None: bar = [1, 2, 3]

Questo potrebbe essere sostituito da un linguaggio leggermente diverso:

def foo(bar = None):
    let mybar = bar or [1, 2, 3]

6
Vorrei tanto che Python avesse una dichiarazione "var". Oltre alla (molto buona) ragione che affermi, renderebbe molto più semplice leggere il codice perché puoi semplicemente scansionare la pagina per individuare tutte le dichiarazioni delle variabili.
jhocking

25
È come se gli sviluppatori di Python ignorassero le lezioni del passato. Non dichiarare variabili, non dichiarare funzioni, è un errore fatto per la prima volta negli anni '50. Quei bug difficili da trovare che derivavano da un errore di battitura difficile da individuare furono fatti sorprendentemente per la prima volta negli anni '50. Questo errore di linguaggio è stato fatto (e successivamente corretto) più volte. Dichiarare le variabili non è un peso enorme. Mi ha salvato il sedere più volte. Inevitabilmente use strict;e use warnings;in perl su una sceneggiatura di qualsiasi dimensione. Python ha privato lo sviluppatore di troppi ausili per il debug.
David Hammen,

19
@David, per essere onesti con Python, genererà un'eccezione se si tenta di accedere a una variabile a cui non è stata assegnata. Molte delle lingue prive di dichiarazioni restituirebbero una sorta di valore predefinito. Di conseguenza, la versione di Python è molto meno problematica di quelle.
Winston Ewert,

1
@yi_H La proposta non era pensata per essere retrocompatibile, o addirittura una proposta reale. La domanda era: "quali sono gli svantaggi di Python" ... beh, non avere vare let(o un meccanismo simile) è uno svantaggio. In altre parole: se fossi stato il designer di Python, avrei fatto qualcosa del genere. Detto questo , le versioni future potrebbero includere questo quando si carica un pacchetto speciale (simile a __future__). Di ', import strict. Ciò non accadrà, poiché richiede hack sintattici ...
Konrad Rudolph,

3
+1 Per aggiungere migliori capacità di programmazione "funzionali".
Evan Plaice,

44

La mia lamentela principale è il threading, che non è altrettanto performante in molte circostanze (rispetto a Java, C e altri) a causa del blocco dell'interprete globale (vedi il discorso "Inside the Python GIL" (link PDF) )

Tuttavia c'è un'interfaccia multiprocesso che è molto facile da usare, tuttavia sarà più pesante sull'uso della memoria per lo stesso numero di processi rispetto ai thread, o difficile se si hanno molti dati condivisi. Il vantaggio, tuttavia, è che una volta che un programma funziona con più processi, può ridimensionarsi su più macchine, cosa che un programma thread non può fare.

Non sono affatto d'accordo sulla critica della documentazione, penso che sia eccellente e migliore della maggior parte, se non di tutte le lingue principali.

Inoltre è possibile rilevare molti dei bug di runtime che eseguono pylint .


2
+1 per pilastro. Non ne ero a conoscenza. La prossima volta che faccio un progetto in Python, lo proverò. Inoltre, il multithreading sembra funzionare correttamente se si utilizza Jython anziché l'implementazione di CPython di riferimento. OTOH Jython è leggermente più lento di CPython, quindi questo può parzialmente vanificare lo scopo.
dsimcha,

3
Il threading non è ben supportato? Le librerie di threading sono presenti da prima della 2.1.
rox0r

2
So che esiste il supporto per il threading, ma rispetto a Java o C, GIL ridurrà davvero le tue prestazioni. Ecco perché il modulo multiprocessore è preferito al threading.
cmcginty,

2
La documentazione è buona se riesci a trovarla. Googling per le classi Java è molto più semplice di Python.
Brendan Long,

@Casey Ho chiarito la formulazione nella risposta, poiché il threading è supportato, mostra solo alcune strane prestazioni (aggiunto un riferimento e anche alcuni collegamenti ai documenti)
dbr

28

Probabilmente , la mancanza di tipizzazione statica, che può introdurre alcune classi di errori di runtime , non vale la flessibilità aggiuntiva fornita dalla tipizzazione duck.


5
Questo è corretto, anche se ci sono strumenti come PyChecker che possono verificare la presenza di errori che un compilatore in linguaggi come farebbe C / Java.
Oliver Weiler,

24
La digitazione dinamica è una decisione di progettazione consapevole, non uno svantaggio.
missingfaktor l'

14
È come dire che la debolezza di Java è la mancanza di una digitazione dinamica.
MAK,

12
@missingfaktor, @MAK, ovviamente la tipizzazione anatra era una funzionalità prevista. Ma la maggior parte delle decisioni di progettazione presentano vantaggi e svantaggi oggettivi. La maggiore flessibilità del codice è un vantaggio della digitazione dinamica e le ulteriori classi di potenziali errori di runtime rappresentano uno svantaggio. La parte soggettiva è se la funzionalità ne vale la pena.
Jacob,

6
La mancanza di tipizzazione statica rende più facile per i programmatori scrivere codice con errori di runtime. In C #, int foo = 4; Console.Write(foo.Length);non viene compilato, quindi l'errore "Int32 non ha una proprietà Length" non può essere inserito accidentalmente nel software pubblicato. In Python, a meno che non si eseguano strumenti secondari opzionali per cercare errori del genere, il codice che accede a membri di oggetti inesistenti può non essere rilevato fino a quando non finisce per causare errori di runtime.
Jacob,

27

Penso che le parti orientate agli oggetti di Python siano un po '"imbullonate". L'intera necessità di passare esplicitamente "sé" a ogni metodo è un sintomo del fatto che il componente OOP non è stato espressamente pianificato , si potrebbe dire; mostra anche le regole di scoping a volte verrucose di Python che sono state criticate in un'altra risposta.

Modificare:

Quando dico che le parti orientate agli oggetti di Python sembrano "imbullonate", intendo a volte che il lato OOP sembra piuttosto incoerente. Prendi Ruby, per esempio: in Ruby tutto è un oggetto e chiami un metodo usando la obj.methodsintassi familiare (ad eccezione degli operatori sovraccarichi, ovviamente); in Python, anche tutto è un oggetto, ma alcuni metodi che chiami come funzione; vale a dire, si sovraccarica __len__per restituire una lunghezza, ma chiamarlo usando len(obj)invece il più familiare (e coerente) obj.lengthcomune in altre lingue. So che ci sono ragioni dietro questa decisione di progettazione, ma non mi piacciono.

Inoltre, il modello OOP di Python non ha alcun tipo di protezione dei dati, ovvero non ci sono membri privati, protetti e pubblici; puoi imitarli usando _e __davanti ai metodi, ma è un po 'brutto. Allo stesso modo, Python non riesce nemmeno a capire bene l'aspetto del passaggio di messaggi di OOP.


17
L'auto-parametro sta semplicemente rendendo esplicito ciò che altre lingue lasciano implicito. Quelle lingue hanno chiaramente un parametro "auto".

13
@Roger Pate: Sì, ma quel bisogno esplicito di "sé" è un po 'fastidioso (e, direi, un'astrazione che perde). Inoltre non è stata presa come una decisione di progettazione deliberata, ma a causa delle "strane" regole di scoping di Python. Non riesco a trovare rapidamente l'articolo, ma c'è un messaggio di posta elettronica di Guido van Rossum che spiega bene perché è necessario il parametro "self".
mipadi,

2
@Roger Pate: nei linguaggi orientati agli oggetti, il passaggio del target come primo parametro potrebbe ancora essere considerato un dettaglio di implementazione. Il mio punto, tuttavia, non è se sia una buona idea o no; il punto è che in Python non è dovuto a una decisione di progettazione consapevole, ma piuttosto a aggirare le verruche nel sistema di scoping.
mipadi,

3
@mipadi: l'aggiornamento ha un ragionamento migliore (quindi rimuoverò il downvote), ma se vedi len come un operatore che sovraccarichi, è più OO in Python. Mi piacerebbe vedere un esempio o un ragionamento su come Python sbaglia il passaggio dei messaggi.

8
Il sé esplicito è una conseguenza del fatto che i metodi sono solo funzioni (e, come notato da Winston, dichiarazioni implicite sulle variabili locali). Sei libero di non gradire quella decisione progettuale, ma chiamare OOP "imbullonato" in una lingua in cui tutto è accessibile come oggetto in fase di esecuzione è sciocco.
ncoghlan,

19

Le cose che non mi piacciono di Python:

  1. Threading (so che è già stato menzionato, ma vale la pena menzionarlo in ogni post).
  2. Nessun supporto per funzioni anonime su più righe ( lambdapuò contenere solo un'espressione).
  3. Mancanza di una funzione / classe di lettura input semplice ma potente (come cino scanfin C ++ e C o Scannerin Java).
  4. Tutte le stringhe non sono unicode per impostazione predefinita (ma corrette in Python 3).

5
Per quanto riguarda (2), penso che ciò sia compensato dalla possibilità di avere funzioni nidificate.
Konrad Rudolph,

3
@KonradRudolph La mia principale preoccupazione con le funzioni nidificate invece delle lambdas multilinea è che l'ordine di lettura viene scambiato.
CookieOfFortune

2
@wkschwartz: raw_inpute 'sys.stdin' sono piuttosto barebone. Non supportano l'ottenimento di input formattati (ad esempio qualcosa come "% d:% d:% d"% (ora, minuti, secondi) da leggere in tempo). Finora Python non ha nulla di simile alla funzionalità di scanf (in C) o Scanner (Java).
MAK

2
@limscoder: tutte le stringhe sono Unicode per impostazione predefinita in Java. Non vedo una buona ragione per avere classi str e unicode separate. IMHO, stringhe e matrici di byte non devono essere rappresentati dalla stessa astrazione. Una classe di stringhe dovrebbe essere per l'archiviazione e la manipolazione del testo - la cui rappresentazione interna non ci interessa davvero. Non dovremmo voler fare cose come troncare / sostituire / cancellare / inserire in un byte specifico all'interno di una stringa - vogliamo farlo con un carattere specifico . È facile dimenticare la distinzione e far esplodere il codice quando viene immesso un input non inglese.
MAK

1
@limscoder: se vuoi vedere unicode semplice, prova Tcl. Ho dovuto passare da Tcl a Python qualche anno fa, e sono rimasto sorpreso da come il supporto unicode di Python primitivo sia in conflitto. È davvero invisibile in Tcl, e un grande dolore in pitone.
Bryan Oakley,

18

Argomenti predefiniti con tipi di dati modificabili.

def foo(a, L = []):
    L.append(a)
    print L

>>> foo(1)
[1]
>>> foo(2)
[1, 2]

Di solito è il risultato di alcuni bug sottili. Penso che sarebbe meglio se creasse un nuovo oggetto elenco ogni volta che era richiesto un argomento predefinito (piuttosto che creare un singolo oggetto da usare per ogni chiamata di funzione).

Modifica: non è un grosso problema, ma quando è necessario fare riferimento a qualcosa nei documenti, significa comunemente che è un problema. Questo non dovrebbe essere richiesto.

def foo(a, L = None):
    if L is None:
        L = []
    ...

Soprattutto quando quello avrebbe dovuto essere il default. È solo uno strano comportamento che non corrisponde a quello che ti aspetteresti e non è utile per un gran numero di circostanze.


Vedo molte lamentele al riguardo, ma perché le persone insistono nell'avere un elenco vuoto (che la funzione modifica) come argomento predefinito? È davvero un grosso problema? Cioè, è un vero problema?
Martin Vilcans,

8
Viola il principio della minima sorpresa. Non ci si aspetterebbe che i parametri di una funzione sopravvivano attraverso le chiamate.
agosto

È una conseguenza del fatto che è un linguaggio di scripting. Rimarrete perplessi da questo errore UNA VOLTA, e mai più. Capire questo bug per te stesso ti dà davvero un calcio nel sedere per ricordarti che sì, questo è ancora un linguaggio di scripting. E questo è solo perché il linguaggio è così buono nel nascondere l'aspetto degli script (supponendo che tu lo usi correttamente).
Zoran Pavlovic,

@ZoranPavlovic per curiosità, perché questa è una conseguenza del fatto che è un linguaggio di scripting? Sembra essere un problema con quando i dati sono associati e perché le liste sono mutabili (che sono due cose che sono normalmente buone, ma finiscono per essere cattive se combinate insieme). Lo stesso problema potrebbe verificarsi in un linguaggio non di scripting se i dati venivano associati al momento della creazione della funzione anziché creare un nuovo elenco ogni volta che veniva chiamata la funzione.
jsternberg,

@aib: Non credo - il parametro qui, come ogni altro oggetto Python - è un puntatore a un oggetto. In questo caso, l'oggetto è mutabile e la variabile viene associata quando viene dichiarata la funzione. Il parametro "sopravvive attraverso le chiamate", ma ciò che sopravvive è il riferimento a un oggetto mutabile.
Patrick Collins,

14

Alcune delle funzionalità di Python che lo rendono così flessibile come linguaggio di sviluppo sono anche viste come importanti svantaggi per chi è abituato all'analisi statica "dell'intero programma" condotta dal processo di compilazione e collegamento in linguaggi come C ++ e Java.

  • Dichiarazione implicita di variabili locali

Le variabili locali vengono dichiarate utilizzando la normale istruzione di assegnazione. Ciò significa che i collegamenti variabili in qualsiasi altro ambito richiedono che il compilatore raccolga annotazioni esplicite (dichiarazioni globali e non locali per ambiti esterni, notazione di accesso agli attributi per ambiti di istanza). Ciò riduce enormemente la quantità di boilerplate necessaria durante la programmazione, ma significa che sono necessari strumenti di analisi statica di terze parti (come pyflakes) per eseguire controlli gestiti dal compilatore in linguaggi che richiedono dichiarazioni di variabili esplicite.

  • "Patching scimmia" è supportato

Il contenuto di moduli, oggetti di classe e persino lo spazio dei nomi incorporato può essere modificato in fase di esecuzione. Questo è estremamente potente, consentendo molte tecniche estremamente utili. Tuttavia, questa flessibilità significa che Python non offre alcune funzionalità comuni ai linguaggi OO tipizzati staticamente. In particolare, il parametro "self" per i metodi di istanza è esplicito piuttosto che implicito (poiché i "metodi" non devono essere definiti all'interno di una classe, possono essere aggiunti in seguito modificando la classe, il che significa che non è particolarmente pratico per passare implicitamente il riferimento all'istanza) e i controlli di accesso agli attributi non possono essere facilmente applicati in base al fatto che il codice sia "dentro" o "fuori" dalla classe (poiché tale distinzione esiste solo mentre la definizione della classe è in esecuzione).

  • Lontano dal metallo

Questo vale anche per molti altri linguaggi di alto livello, ma Python tende a sottrarre la maggior parte dei dettagli hardware. I linguaggi di programmazione di sistemi come C e C ++ sono ancora molto più adatti alla gestione dell'accesso diretto all'hardware (tuttavia, Python parlerà abbastanza felicemente a quelli tramite i moduli di estensione CPython o, più facilmente, tramite la ctypeslibreria).


12
  1. Uso del rientro per i blocchi di codice anziché {} / begin-end, qualunque cosa.
  2. Ogni linguaggio moderno più recente ha un corretto ambito lessicale, ma non Python (vedi sotto).
  3. Documenti caotici (confronta con la documentazione Perl5, che è superba).
  4. Giacca dello stretto (c'è solo un modo per farlo).

Esempio di scoping rotto; trascrizione dalla sessione dell'interprete:

>>> x=0
>>> def f():
...     x+=3
...     print x
... 
>>> f()
Traceback (most recent call last):
  File "", line 1, in ?
  File "", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment

globale nonlocalsono state introdotte parole chiave per correggere questa stupidità progettuale.


2
per quanto riguarda lo scoping, potrebbe valere la pena per i curiosi guardare python.org/dev/peps/pep-3104 per capire il ragionamento del metodo attuale.
Winston Ewert,

Accetto con +1. Quindi, +1.
Jas,

34
Avere un modo per farlo è un vantaggio. Quando leggi il codice di qualcun altro non hai mai decifrare mai una singola istruzione. Una volta che gli idiomi sono fissi nel tuo cervello, dovresti avere un riconoscimento immediato.
rox0r

9
Completamente d'accordo con @ rox0r. La "giacca dritta" impedisce ogni sorta di guerre di sintassi.
keithjgrant,

8
Ad essere sincero, raramente ho bisogno delle parole chiave globalo nonlocalin Python. Così raramente che dimentico che questo problema esiste e devo ricominciare a cercarlo su Google poche volte, nonostante il fatto che scrivo codice Python ogni giorno al lavoro. Per me, il codice che deve modificare le variabili globali (o peggio, le variabili non globali esterne) è un odore di codice. Di solito c'è (non sempre) un modo migliore.
Ben

11

Trovo la combinazione di sintonia orientata agli oggetti this.method()e procedurale / funzionale di Python method(this)molto inquietante:

x = [0, 1, 2, 3, 4]
x.count(1)
len(x)
any(x)
x.reverse()
reversed(x)
x.sort()
sorted(x)

Ciò è particolarmente negativo perché un gran numero di funzioni (piuttosto che metodi) sono appena scaricate nello spazio dei nomi globale : metodi relativi a liste, stringhe, numeri, costruttori, metaprogrammazione, tutti mescolati in un grande elenco in ordine alfabetico.

Per lo meno, linguaggi funzionali come F # hanno tutte le funzioni opportunamente spaziate nei moduli:

List.map(x)
List.reversed(x)
List.any(x)

Quindi non sono tutti insieme. Inoltre, questo è uno standard seguito in tutta la biblioteca, quindi almeno è coerente.

Capisco le ragioni per fare la funzione funzione vs metodo , ma penso ancora che sia una cattiva idea mescolarli in questo modo. Sarei molto più felice se fosse seguita la sintassi del metodo, almeno per le operazioni comuni:

x.count(1)
x.len()
x.any()
x.reverse()
x.reversed()
x.sort()
x.sorted()

Indipendentemente dal fatto che i metodi stiano mutando o meno, averli come metodi sull'oggetto presenta diversi vantaggi:

  • Posto unico per cercare le operazioni "comuni" su un tipo di dati: altre librerie / ecc. possono avere altre cose fantasiose che possono fare ai tipi di dati ma le operazioni "predefinite" sono tutte nei metodi dell'oggetto.
  • Non è necessario continuare a ripetere la Modulechiamata Module.method(x). Prendendo l'esempio di Elenco funzionale sopra, perché devo continuare a ripetere List? Dovrebbe sapere che è una Liste non voglio chiamare la Navigation.map()funzione su di essa! L'uso della x.map()sintassi lo mantiene ASCIUTTO e ancora inequivocabile.

E ovviamente ha dei vantaggi rispetto al modo di fare tutto nello spazio dei nomi globale . Non è che l'attuale modo sia incapace di fare le cose. È anche piuttosto terse ( len(lst)), dal momento che nulla è spaziato dai nomi! Comprendo i vantaggi nell'uso delle funzioni (comportamento predefinito, ecc.) Rispetto ai metodi, ma ancora non mi piace.

È solo disordinato. E nei grandi progetti, la confusione è il tuo peggior nemico.


1
sì ... mi manca molto lo stile LINQ (sono sicuro che LINQ non è il primo ad implementarlo, ma ne ho più familiarità) la gestione delle liste.
CookieOfFortune

1
Non pensare a len (x) come un metodo. "len" è una funzione. Python ha funzioni e metodi e non vedo nulla di sbagliato in questo approccio. La mancanza di funzioni adeguate è, di solito, la fonte di molte digitazioni inutili.
rbanffy,

So che len()è una funzione e quali sono i vantaggi. Ho anche affermato perché penso che sia una cattiva idea, perché penso che le funzioni globali siano un'idea particolarmente negativa e perché penso che i metodi forniscano un metodo conveniente per organizzare e definire la tua funzionalità =)
Haoyi

Non credo che 42 (o 43?) Parole chiave siano un numero "grande". Che comprende anche le cose come def, classe altre chiamate non funzioni. Confronta quello con oltre 100 nella maggior parte delle altre lingue popolari. Inoltre, si consideri la linea da import this: Namespaces are one honking great idea -- let's do more of those!. Penso che potresti fraintendere gli spazi dei nomi di Python;)
Wayne Werner,

8

Mancanza di omoiconicità .

Python ha dovuto attendere 3.x per aggiungere una parola chiave "with". In qualsiasi linguaggio omoiconico avrebbe potuto essere banalmente aggiunto in una biblioteca.

La maggior parte degli altri problemi che ho visto nelle risposte sono di 3 tipi:

1) Cose che possono essere riparate con gli strumenti (es. Pyflakes) 2) Dettagli di implementazione (GIL, prestazioni) 3) Cose che possono essere riparate con standard di codifica (cioè caratteristiche che le persone vorrebbero non esistere)

# 2 non è un problema con la lingua, IMO # 1 e # 3 non sono problemi seri.


1
withera disponibile da Python 2.5 con from __future__ import with_statement, ma sono d'accordo, ho a volte trovato un peccato che le dichiarazioni come if/ for/ print/ etc sono "speciali" invece di funzioni regolari
DBR

7

Python è la mia lingua preferita in quanto è molto espressivo, ma ti impedisce ancora di fare troppi errori. Ho ancora alcune cose che mi infastidiscono:

  • Nessuna vera funzione anonima. Lambda può essere utilizzato per le funzioni a singola istruzione e l' withistruzione può essere utilizzata per molte cose in cui si utilizza un blocco di codice in Ruby. Ma in alcune situazioni rende le cose un po 'più goffe di quanto dovrebbero essere. (Lungi dall'essere maldestro come sarebbe in Java, ma comunque ...)

  • Qualche confusione nella relazione tra moduli e file. L'esecuzione di "python foo.py" dalla riga di comando è diversa da "import foo". Anche le importazioni relative in Python 2.x possono causare problemi. Tuttavia, i moduli di Python sono molto meglio delle corrispondenti funzionalità di C, C ++ e Ruby.

  • Esplicito self. Anche se capisco alcune delle ragioni di ciò, e anche se uso Python quotidianamente, tendo a commettere l'errore di dimenticarlo. Un altro problema è che diventa un po 'noioso creare una classe da un modulo. Il sé esplicito è legato al limitato ambito di cui altri si sono lamentati. L'ambito più piccolo in Python è l'ambito della funzione. Se mantieni piccole le tue funzioni, come dovresti, non è un problema da solo e IMO fornisce spesso un codice più pulito.

  • Alcune funzioni globali, come ad esempio len, che ti aspetteresti di essere un metodo (che in realtà è dietro le quinte).

  • Rientro significativo. Non l'idea stessa, che penso sia grandiosa, ma poiché questa è l'unica cosa che impedisce a così tante persone di provare Python, forse Python starebbe meglio con alcuni simboli (facoltativi) di inizio / fine. Ignorando quelle persone, potrei vivere totalmente con una dimensione forzata anche per il rientro.

  • Che non è la lingua integrata dei browser Web, anziché JavaScript.

Di questi reclami, è solo il primo a cui tengo abbastanza da pensare che debba essere aggiunto alla lingua. Gli altri sono piuttosto minori, tranne l'ultimo, il che sarebbe fantastico se fosse successo!


+1 Mi chiedo se scrivere datetime.datetime.now()quando un progetto potrebbe scrivere datetime.nowe quindi mescolare due progetti in un modo per scriverlo esclude l'altro e sicuramente questo non sarebbe accaduto in Java che non nominerebbe un modulo come un file (?) se vedi come il modo comune sembra avere il modulo che ci confonde con il file quando entrambi gli usi sono praticati ed espliciti, selfprovo ancora a capire poiché le chiamate non hanno lo stesso numero di argomenti delle funzioni. E potresti pensare che il VM Python sia lento?
Niklas Rosencrantz,

Per quanto riguarda il tuo problema con la parola chiave self esplicita. Potrei suggerire di usare un buon IDE Python per questo? So che PyDev su Eclipse completa automaticamente la porzione di sé di una firma di funzione se rileva che stai scrivendo all'interno di una classe.
Zoran Pavlovic

5

Python non è completamente maturo: il linguaggio python 3.2 in questo momento ha problemi di compatibilità con la maggior parte dei pacchetti attualmente distribuiti (in genere sono compatibili con python 2.5). Questo è un grande svantaggio che attualmente richiede maggiori sforzi di sviluppo (trova il pacchetto necessario; verifica la compatibilità; sopporta la scelta di un pacchetto non buono che potrebbe essere più compatibile; prendi la versione migliore, aggiornala alla 3.2 che potrebbe richiedere giorni; poi iniziare a fare qualcosa di utile).

Probabilmente a metà 2012 questo sarà meno di uno svantaggio.

Nota che credo di essere stato sottratto da un fan-boy. Durante una discussione con gli sviluppatori, tuttavia, il nostro team di sviluppatori di alto livello ha raggiunto la stessa conclusione.

La maturità in un senso principale significa che un team può utilizzare la tecnologia ed essere rapidamente operativo senza rischi nascosti (compresi i problemi di compatibilità). I pacchetti Python di terze parti e molte app non funzionano al di sotto di 3.2 per la maggior parte dei pacchetti oggi. Questo crea più lavoro di integrazione, test, reimplementazione della tecnologia stessa invece di risolvere il problema attuale == tecnologia meno matura.

Aggiornamento per giugno 2013: Python 3 presenta ancora problemi di maturità. Ogni tanto un membro del team menziona un pacchetto necessario, quindi dice "tranne che è solo per 2.6" (in alcuni di questi casi ho implementato una soluzione alternativa tramite il socket localhost per utilizzare il pacchetto solo 2.6 con 2.6 e il resto di i nostri strumenti rimangono con 3.2). Nemmeno MoinMoin, il wiki di pure-python, è scritto in Python 3.


2
Sono d'accordo con te solo se la tua definizione di maturità non è compatibile con una versione incompatibile con il design .
Tshepang,

3
Concordo sul fatto che i due flussi incompatibili di Python siano un problema (sebbene comprensibile il motivo per cui è stato fatto), ma non lo vedo come un problema di "maturità".
Winston Ewert,

La maturità in un certo senso significa che un team può utilizzare la tecnologia ed essere subito operativo senza rischi nascosti (inclusi i problemi di compatibilità). I pacchetti Python di terze parti e molte app non funzionano al di sotto di 3.2 per la maggior parte dei pacchetti oggi. Questo crea più lavoro di integrazione, test, reimplementazione della tecnologia stessa invece di risolvere il problema attuale == tecnologia meno matura.
Jonathan Cline IEEE,

2
Quindi basta usare Python 2.x. Sai ... la versione che tutti usano. Oppure leggi la documentazione dei pacchetti per 2 secondi per capire con quali versioni è compatibile.
jsternberg,

2
"Solo perché python 3.0 è stato rilasciato da qualche tempo non significa che sia la versione che dovresti usare. Python 3.0 e 2.x sono in fase di sviluppo contemporaneamente. Spero che in futuro saremo tutti in grado di usare python 3.0, ma per ora usare 2.x è una buona soluzione "-> Questo è un modo di dire di 500 caratteri: non è ancora maturo.
Jonathan Cline IEEE,

4

Lo scoping di Python è gravemente rotto, il che rende molto imbarazzante la programmazione orientata agli oggetti in Python.


8
Puoi fare un esempio? (Sono sicuro che hai ragione, ma vorrei un esempio)
Winston Ewert,

24
Mi piace Python ma disprezzo assolutamente dover mettere self.di fronte ogni riferimento a una proprietà e un metodo di istanza. Rende impossibile usare Python per creare un DSL come è così facile da fare in Ruby.
Adam Crossland,

35
Non trovo imbarazzante se stesso, mi piace l'esplicito.
Winston Ewert,

9
Non vedo quale sia il grosso del sé esplicito. In C ++, Java e D, le persone spesso rendono esplicite le variabili membro comunque per convenzione, ad esempio prefissandole con un carattere di sottolineatura.
dsimcha,

7
Usa self in metodi diversi dalla loro dichiarazione: def foo (self) ma self.foo (). Trovo che questa miscela di definizione esplicita ma roba implicita dietro le quinte non sia troppo carina.
LennyProgrammers,

4

Le mie lamentele su Python:

  • OOP imbullonato (vedi la risposta di @ mipadi per l'elaborazione al riguardo)
  • Implementazione non corretta di lambda
  • Problemi di portata
  • Nessuna raccolta persistente nella libreria standard
  • Scarsa amabilità ai DSL integrati

Perché il downvote?
missingfaktor il

Non sono il downvoter, ma puoi spiegare perché pensi che l'OO sia bloccato? Python ha sempre avuto OO, è una parte fondamentale del linguaggio.
Daenyth,

Vedi la risposta di @ mipadi.
missingfaktor,


4

I modificatori di accesso in Python non sono esecutivi - rende difficile scrivere codice ben strutturato e modularizzato.

Suppongo che faccia parte dell'ambito rotto di @ Mason - un grosso problema in generale con questo linguaggio. Per il codice che dovrebbe essere leggibile, sembra abbastanza difficile capire cosa può e dovrebbe essere nell'ambito e quale valore sarà in un dato momento - Attualmente sto pensando di passare dal linguaggio Python a causa di questi inconvenienti .

Solo perché "siamo tutti adulti consenzienti" non significa che non commettiamo errori e non lavoriamo meglio all'interno di una struttura solida, soprattutto quando si lavora su progetti complessi: il rientro e i caratteri di sottolineatura insignificanti non sembrano essere sufficienti .


Quindi la mancanza di controlli di accesso è negativa ... ma anche l'ambito esplicito delle scritture variabili su qualsiasi spazio dei nomi non locale è negativo?
ncoghlan,

@ncoghlan: 1 - questa funzionalità è standard in molte lingue moderne, a seconda della configurazione del progetto. 2 -È sotto il controllo del programmatore. 3 - non sono sicuro di cosa ci sia di eccezionale - puoi facilmente controllare il tuo ambito con alcune impostazioni del progetto nella maggior parte delle lingue / IDE compilate. Se "siamo tutti adulti consenzienti", dovremmo essere in grado di prendere le nostre decisioni e adeguare la portata in base al nostro particolare livello di comfort.
Vettore

2
Il fatto è che le persone che chiedono "controlli di accesso forzati" ci stanno chiedendo di eliminare una delle cose che rendono Python un linguaggio colla così grande: è deliberatamente difficile per gli sviluppatori controllare come il loro codice verrà successivamente utilizzato. Quanta parte del boilerplate nei modelli C ++ e Java esiste solo per aggirare i controlli di accesso forzati? Posso sicuramente capire le persone che scelgono di non usare Python per questi motivi, ma l'applicazione statica non sostituirà mai test rigorosi.
ncoghlan,

1
@ncoghlan - per me le cose grandi di Python sono l'eleganza della sintassi e la succinta - espressività. E come ho detto, lo scoping ha meno a che fare con i programmatori che fanno confusione con cose che non dovrebbero di quanto non faccia con la struttura e l'organizzazione del codice - quindi il concetto di "adulti consenzienti" è controverso. Lavoro su progetti complessi, non su semplici utility e script - il codice deve essere attentamente modulare e strutturato - i modificatori di accesso sono uno dei modi più importanti per garantirlo.
Vettore

1
E la revisione del codice, la formazione e l'analisi dell'accoppiamento sono altri. Per me, i controlli di accesso forzati rientrano nella stessa categoria della tipizzazione statica: aiutano a fornire un po 'più di fiducia nella correttezza (ma non abbastanza per evitare la necessità di test approfonditi), ma a un costo elevato nella produttività dello sviluppo. (A livello pratico, anche i controlli di accesso agli attributi di classe non si adattano al modello a oggetti di Python in cui i metodi sono solo normali funzioni recuperate dalle classi. Il limite "interno / esterno" per le classi non esiste davvero, quindi non può essere applicato)
ncoghlan,

3
  1. Le prestazioni non sono buone, ma stanno migliorando con pypy,
  2. Il GIL impedisce l'uso del threading per velocizzare il codice (anche se di solito si tratta di un'ottimizzazione prematura),
  3. È utile solo per la programmazione dell'applicazione,

Ma ha alcune grandi funzionalità di riscatto:

  1. È perfetto per RAD,
  2. È facile interfacciarsi con C (e per C incorporare un interprete Python),
  3. È molto leggibile,
  4. È facile da imparare,
  5. È ben documentato,
  6. Le batterie sono davvero incluse, la sua libreria standard è enorme e pypi contiene moduli praticamente per tutto,
  7. Ha una comunità sana.

Cosa ha ispirato a menzionare i vantaggi? La domanda per i problemi. Comunque, cosa vuoi dire è utile solo per la programmazione dell'applicazione? Quale altra programmazione c'è? A cosa non serve specificamente?
Tshepang,

5
Ho elencato i vantaggi perché penso che superino i contro. Hai mai provato a implementare un modulo del kernel Linux in Python.
dan_waterworth,

3

Prediligo Python e il primo svantaggio che mi viene in mente è quando commentando un'affermazione come if myTest():allora devi cambiare il rientro dell'intero blocco eseguito che non avresti a che fare con C o Java. In effetti in Python invece di commentare una clausola if invece ho iniziato a commentarla in questo modo: `se True: #myTest (), quindi non dovrò nemmeno cambiare il seguente blocco di codice. Poiché Java e C non si basano sul rientro, è più facile commentare le dichiarazioni con C e Java.


1
Modificheresti seriamente il codice C o Java per modificare il livello di blocco di alcuni codici senza modificarne il rientro?
Ben

4
@Ben Temporaneamente, sì ...
alternativa il

1
@ben stesso qui.
Christopher Mahan,

2
Uso il trucco per passare if something()a if False and something(). Un altro trucco è "commentare" usando una stringa multilinea.
Martin Vilcans,

1
@Martin Naturalmente! if False ...
Christopher Mahan,

3

La spedizione multipla non si integra bene con il sistema di tipo a spedizione singola stabilito e non è molto performante.

Il caricamento dinamico è un grosso problema su file system paralleli in cui la semantica simile a POSIX porta a catastrofici rallentamenti per operazioni ad alta intensità di metadati. Ho colleghi che hanno bruciato un quarto di milione di core-hour solo caricando Python (con numpy, mpi4py, petsc4py e altri moduli di estensione) caricati su core 65k. (La simulazione ha prodotto nuovi significativi risultati scientifici, quindi ne è valsa la pena, ma è un problema quando viene bruciato più di un barile di petrolio per caricare Python una volta.) L'incapacità di collegarsi staticamente ci ha costretti a fare grandi contorsioni per ottenere tempi di caricamento ragionevoli su larga scala, inclusa l'applicazione di patch a libc-rtld per consentire l' dlopenaccesso collettivo al file system.


Wow, sembra altamente tecnico, hai qualche materiale di riferimento, esempi, post di blog o articoli sull'argomento? Mi chiedo se potrei essere esposto a tali casi in un prossimo futuro.
vincent,

Aron ha tenuto un discorso a SciPy 2012 . Il dlopenmateriale è nella nostra libreria collfs . Questo repository contiene anche ulteriori trucchi zipimport ispirati alla memorizzazione nella cache del percorso di Asher Langton. Stiamo lavorando per una migliore distribuzione e un documento.
Jed

3
  • un bel po 'di librerie e software di terze parti molto diffusi che sono ampiamente usati, non sono abbastanza pitonici. Alcuni esempi: soaplib, openerp, reportlab. La critica è fuori portata, è lì, è ampiamente usata, ma confonde la cultura del pitone (fa male il motto che dice "Dovrebbe esserci uno - e preferibilmente solo un - modo evidente per farlo"). Successi pitonici noti (come django o trac) sembrano essere l'eccezione.
  • la profondità potenzialmente illimitata di astrazione di istanza, classe, metaclasse è concettualmente bella e unica. Ma per padroneggiarlo devi conoscere profondamente l'interprete (in quale ordine viene interpretato il codice Python, ecc.). Non è ampiamente conosciuto e usato (o usato correttamente), mentre una simile magia nera come i generici di C #, che è concettualmente più contorta (IMHO) sembra più ampiamente conosciuta e usata, proporzionalmente.
  • per avere una buona conoscenza della memoria e del modello di threading, devi avere abbastanza esperienza con Python, perché non ci sono specifiche complete. Sai solo cosa funziona, forse perché hai letto le fonti dell'interprete o hai sperimentato stranezze e hai scoperto come risolverle. Ad esempio, ci sono solo riferimenti forti o deboli, non i riferimenti morbidi e fantasma di Java. Java ha un thread per la garbage collection mentre non esiste una risposta formale su quando la garbage collection avviene in Python; puoi semplicemente osservare che la garbage collection non avviene se non viene eseguito alcun codice Python e concludere che a volte succede probabilmente quando si tenta di allocare memoria. Può essere complicato quando non sai perché non è stata rilasciata una risorsa bloccata (la mia esperienza al riguardo è stata mod_python in freeswitch).

Ad ogni modo, Python è la mia lingua principale da 4 anni. Essere fanboys, elitari o monomaniaci non fa parte della cultura del pitone.


+1. Le specifiche per il modello di memoria e threading sono attive. Ma FWIW, il Garbage Collector Java su un thread (e quasi tutto il resto sul GC) non è un aspetto del linguaggio Java o delle specifiche della VM in sé, ma è una questione di implementazione di una particolare JVM. Tuttavia, la principale JVM Sun / Oracle è ampiamente documentata rispetto al comportamento e alla configurabilità del GC, nella misura in cui ci sono interi libri pubblicati sulla messa a punto di JVM. In teoria si potrebbe documentare CPython allo stesso modo, indipendentemente dalle specifiche del linguaggio.
Andrew Janke,

2
  • Strano OOP:
    • len(s)attraverso __len__(self)e altri "metodi speciali"
    • metodi extra speciali che potrebbero essere derivati ​​da altri metodi speciali ( __add__e __iadd__per +e +=)
    • self come primo parametro del metodo
    • puoi dimenticare di chiamare il costruttore della classe base
    • nessun modificatore di accesso (privato, protetto ...)
  • nessuna definizione costante
  • nessuna immutabilità per tipi personalizzati
  • GIL
  • scarse prestazioni che portano a un mix di Python e C e problemi con build (ricerca di librerie C, dipendenze della piattaforma ...)
  • cattiva documentazione, specialmente nelle librerie di terze parti
  • incompatibilità tra Python 2.xe 3.x
  • strumenti di analisi del codice scadente (rispetto a ciò che viene offerto per linguaggi tipicamente statici come Java o C #)

5
Personalmente penso che l'incompatibilità tra 2.xe 3.x sia uno dei maggiori vantaggi di Python. Certo, è anche uno svantaggio. Ma l'audacia degli sviluppatori di rompere la compatibilità all'indietro significa anche che non hanno dovuto portare avanti un'infinità di giri. Più lingue necessitano di tale revisione.
Konrad Rudolph,

0

"Immutabilità" non è esattamente il suo punto di forza. I numeri, le tuple e le stringhe di AFAIK sono immutabili, tutto il resto (ovvero gli oggetti) è mutabile. Confronta quello con linguaggi funzionali come Erlang o Haskell in cui tutto è immutabile (per impostazione predefinita, almeno).

Tuttavia, l'immutabilità brilla davvero con la concorrenza *, che non è anche il punto di forza di Python, quindi almeno è conseguente.

(* = Per i nitpicker: intendo la concorrenza che è almeno parzialmente parallela. Immagino che Python sia d'accordo con la concorrenza "single-threaded", in cui l'immutabilità non è così importante. (Sì, gli amanti del FP, so che l'immutabilità è ottimo anche senza concorrenza.))


0

Mi piacerebbe avere costrutti esplicitamente paralleli. Più spesso, quando scrivo un elenco di comprensione come

[ f(x) for x in lots_of_sx ]

Non mi interessa l'ordine in cui gli elementi verranno elaborati. A volte, non mi importa nemmeno in quale ordine vengano restituiti.

Anche se CPython non riesce a farlo bene quando la mia f è Python puro, comportamenti come questo potrebbero essere definiti per altre implementazioni da utilizzare.


// genera gruppi di thread // passa la coda Que a tutti i thread que.extend ([x per x in lots_of_sx]) que.wait () # Attendi che tutti i lotti di thread vengano elaborati dai thread.
Zoran Pavlovic

0

Python non ha ottimizzazione della coda, soprattutto per motivi filosofici . Ciò significa che la ricorsione della coda su strutture di grandi dimensioni può costare memoria O (n) (a causa dello stack non necessario che viene conservato) e richiederà di riscrivere la ricorsione come un ciclo per ottenere memoria O (1).

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.