Quais são as desvantagens do Python? [fechadas]


147

Atualmente, o Python parece estar com toda a raiva, e não é merecedor de elogios - pois é realmente uma linguagem com a qual quase se gosta de receber um novo problema para resolver. Mas, como um homem sábio disse uma vez (chamando-o de homem sábio apenas porque não tenho idéia de quem realmente disse isso; não tenho certeza se ele era tão sábio), para realmente conhecer uma língua, não se sabe apenas sua sintaxe, design, etc., vantagens, mas também suas desvantagens. Nenhuma linguagem é perfeita, algumas são melhores que outras.

Então, o que seria, na sua opinião, desvantagens objetivas do Python.

Nota: Eu não estou pedindo uma comparação de idiomas aqui (por exemplo, C # é melhor que Python porque ... yadda yadda yadda) - mais uma opinião objetiva (em algum nível) sobre quais recursos de linguagem foram mal projetados, se, quais são talvez alguns estão faltando nele e assim por diante. Se deve usar outro idioma como comparação, mas apenas para ilustrar um ponto que seria difícil de elaborar de outra maneira (isto é, para facilitar o entendimento)


50
Penso que esta é uma questão subjetiva útil, e seria uma pena encerrá-la.
Eric Wilson

25
Parece haver um python-fanboy aqui que apenas rebate todas as respostas anti-python.
Zvrba

2
@TMN: Isso ainda trata os espaços em branco como tokens, mas não os retorna - e é exatamente o que a gramática do Python também faz.

9
@ Roger: a convenção sobre SO é comentar votos negativos. Como este é um site para opiniões subjetivas , não vejo razão para votos negativos, esp. sem comentários. Então, eu mantenho meu "xingamento".
Zvrba 29/10/10

8
@zvrba: Os votos negativos ainda significam "não são úteis", como sempre.

Respostas:


109

Eu uso o Python com alguma regularidade e, no geral, considero uma linguagem muito boa. No entanto, nenhuma linguagem é perfeita. Aqui estão as desvantagens em ordem de importância para mim pessoalmente:

  1. É lento. Quero dizer muito, muito devagar. Muitas vezes isso não importa, mas definitivamente significa que você precisará de outro idioma para esses bits críticos de desempenho.

  2. Funções aninhadas meio que sugam que você não pode modificar variáveis ​​no escopo externo. Edit: Eu ainda uso o Python 2 devido ao suporte da biblioteca, e essa falha de design me irrita, mas aparentemente ele foi corrigido no Python 3 devido à declaração não - local . Mal posso esperar para que as bibliotecas que eu uso sejam portadas, para que essa falha possa ser enviada para o monte de cinzas da história para sempre.

  3. Faltam alguns recursos que podem ser úteis para a biblioteca / código genérico e o IMHO é a simplicidade levada a extremos prejudiciais. Os mais importantes que consigo pensar são os tipos de valores definidos pelo usuário (acho que eles podem ser criados com a metaclasse mágica, mas nunca tentei) e o parâmetro da função ref.

  4. Está longe do metal. Precisa escrever primitivas de encadeamento ou código do kernel ou algo assim? Boa sorte.

  5. Embora eu não me importe com a falta de capacidade de capturar erros semânticos antecipadamente como uma compensação pelo dinamismo que o Python oferece, gostaria que houvesse uma maneira de capturar erros sintáticos e coisas bobas, como digitar nomes de variáveis ​​sem precisar executar o código.

  6. A documentação não é tão boa quanto linguagens como PHP e Java que têm fortes bases corporativas.


60
@ Casey, eu tenho que discordar. O índice é horrível - tente procurar a withinstrução ou métodos em a list. Qualquer coisa abordada no tutorial é basicamente impossível de pesquisar. Tenho uma sorte muito melhor com a documentação da Microsoft para C ++.
Mark Ransom

17
Cerca de 5 - basta usar flocos de neve. Foi escrito para capturar exatamente esses erros.
Alexander Solovyov

4
Em relação à velocidade: com o surgimento do PyPy, muitos usuários do Python agora poderão lidar com o problema de velocidade apenas usando um intérprete com um compilador JIT integrado (por enquanto, usuários do Python 3 e usuários de módulos de extensão C não manipulados pelo cpyext não tem essa opção).
Ncoghlan

29
Eu desprezo os documentos do Python. Eles são mais bonitos do que a maioria, com certeza, mas muitas vezes muitas informações úteis são agrupadas em uma página, como métodos em strings e listas - e todos os tipos de sequência também são agrupados. Quando pesquiso essas informações, chego a um volume enorme e preciso pesquisar na página para encontrar o que quero. Também acho difícil ler o índice nestas páginas, e às vezes é difícil dizer qual seção eu quero.
Carson Myers

5
Como a distância do metal pode ser um argumento? O Python já pretendeu ser uma linguagem de sistemas?
Mark Canlas 9/09/12

66

Odeio que o Python não consiga distinguir entre declaração e uso de uma variável. Você não precisa de digitação estática para fazer isso acontecer. Seria bom ter uma maneira de dizer "essa é uma variável que deliberadamente declaro e pretendo introduzir um novo nome, isso não é um erro de digitação".

Além disso, eu costumo usar variáveis ​​Python em um estilo de gravação única, ou seja, trato as variáveis ​​como imutáveis ​​e não as modifico após a primeira atribuição. Graças a recursos como compreensão de lista, isso é incrivelmente fácil e facilita o acompanhamento do código.

No entanto, não posso documentar esse fato. Nada no Python me impede de substituir ou reutilizar variáveis.

Em resumo, eu gostaria de ter duas palavras-chave no idioma: vare let. Se eu escrever em uma variável não declarada por nenhuma delas, o Python deve gerar um erro. Além disso, letdeclara variáveis ​​como somente leitura, enquanto varvariáveis ​​são "normais".

Considere este exemplo:

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

Observe que os tipos ainda estão implícitos (mas as letvariáveis ​​são digitadas estaticamente para todos os efeitos, pois não podem ser recuperadas para um novo valor, enquanto as varvariáveis ​​ainda podem ser digitadas dinamicamente).

Finalmente, todos os argumentos do método devem ser automaticamente let, ou seja, devem ser somente leitura. Geralmente, não há bons motivos para modificar um parâmetro, exceto pelo seguinte idioma:

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

Isso pode ser substituído por um idioma ligeiramente diferente:

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

6
Eu gostaria tanto que o Python tivesse uma declaração "var". Além do (muito bom) motivo pelo qual você declara, também seria muito mais fácil ler o código, porque você pode simplesmente varrer a página para localizar todas as declarações de variáveis.
Jhocking

25
É como se os desenvolvedores de python ignorassem as lições do passado. Não declarar variáveis, não declarar funções, é um erro cometido pela primeira vez na década de 1950. Os bugs difíceis de encontrar que resultaram de erros de digitação difíceis de detectar foram surpreendentemente feitos pela primeira vez na década de 1950. Este erro de idioma foi cometido (e posteriormente corrigido) uma e outra vez. Declarar variáveis ​​não é um fardo enorme. Ele salvou minha bunda várias vezes. Eu inevitavelmente use strict;e use warnings;perl em um script de qualquer tamanho. O Python retirou o desenvolvedor de muitos auxiliares de depuração.
David Hammen

19
@ David, para ser justo com o python, isso criará uma exceção se você tentar acessar uma variável que não foi atribuída. Muitos dos idiomas que não possuem declarações retornariam algum tipo de valor padrão. Como resultado, a versão do Python é muito menos problemática do que aquelas.
Winston Ewert 23/07

1
@yi_H A proposta não era para ser compatível com versões anteriores - ou mesmo uma proposta real. A questão era: "quais são as desvantagens do Python" ... bem, não ter vare let(ou um mecanismo semelhante) é uma desvantagem. Em outras palavras: se eu fosse o designer do Python, teria feito algo assim. Dito isto , as versões futuras podem incluir isso quando você carrega um pacote especial (semelhante a __future__). Diga import strict,. Isso não vai acontecer, porém, uma vez que requer hackers sintáticos ...
Konrad Rudolph

3
+1 Para adicionar melhores habilidades de programação 'funcionais'.
Evan Plaice

44

Minha principal reclamação é o threading, que não é tão eficiente em muitas circunstâncias (em comparação com Java, C e outras) devido ao bloqueio global de intérpretes (consulte a palestra "Inside the Python GIL" (link em PDF) )

No entanto, há uma interface de multiprocessos muito fácil de usar, mas será mais pesada no uso de memória para o mesmo número de processos versus threads, ou difícil se você tiver muitos dados compartilhados. O benefício, no entanto, é que, quando você tem um programa trabalhando com vários processos, ele pode ser escalonado em várias máquinas, algo que um programa encadeado não pode fazer.

Eu realmente discordo da crítica da documentação, acho que é excelente e melhor do que a maioria, se não todas as principais línguas existentes.

Além disso, você pode capturar muitos dos erros de tempo de execução executando o pylint .


2
+1 para pilão. Eu não sabia disso. Da próxima vez que fizer um projeto em Python, testarei. Além disso, o multithreading parece funcionar bem se você usar o Jython em vez da implementação de referência do CPython. OTOH Jython é um pouco mais lento que o CPython, portanto, isso pode anular parcialmente o objetivo.
dsimcha

3
O encadeamento não é bem suportado? As bibliotecas de encadeamento estão lá desde antes do 2.1.
rox0r

2
Sei que há suporte para segmentação, mas comparado ao Java ou C, o GIL realmente diminuirá seu desempenho. É por isso que o módulo de multiprocessamento é preferível ao threading.
cmcginty

2
A documentação é boa se você conseguir encontrá-la. Pesquisando classes Java é muito mais fácil que Python.
Brendan Long

@Casey eu esclareceu a redacção da resposta, uma vez rosqueamento é suportado, apenas exibe algumas desempenho estranho (adicionado uma referência e alguns links para docs também)
DBR

28

Indiscutivelmente , a falta de digitação estática, que pode introduzir certas classes de erros de tempo de execução , não vale a flexibilidade adicional oferecida pela digitação de pato.


5
Isso está correto, embora existam ferramentas como o PyChecker que podem verificar erros que um compilador em linguagens como o C / Java faria.
Oliver Weiler

24
A digitação dinâmica é uma decisão consciente do projeto, não uma desvantagem.
missingfaktor

14
É o mesmo que dizer que a fraqueza do Java é a falta de digitação dinâmica.
MAK

12
@missingfaktor, @MAK, obviamente a digitação com patos era uma característica pretendida. Mas a maioria das decisões de design apresenta vantagens e desvantagens objetivas. A flexibilidade de código adicionada é um benefício da digitação dinâmica, e as classes adicionais de possíveis erros de tempo de execução são uma desvantagem. A parte subjetiva é se o recurso vale a pena.
Jacob

6
A falta de digitação estática facilita para os programadores escreverem códigos com erros de tempo de execução. Em C #, int foo = 4; Console.Write(foo.Length);não é compilado; portanto, o erro "Int32 não possui uma propriedade Comprimento" não pode ser acessado acidentalmente no software publicado. No python, a menos que você execute ferramentas secundárias opcionais para procurar erros como esse, o código que acessa membros não existentes de objetos pode passar despercebido até acabar causando erros de tempo de execução.
Jacob

27

Eu acho que as partes orientadas a objetos do Python parecem "apertadas". Toda a necessidade de passar explicitamente o "eu" para todo método é um sintoma de que seu componente OOP não foi expressamente planejado , você poderia dizer; também mostra as regras de escopo às vezes vergonhosas do Python que foram criticadas em outra resposta.

Editar:

Quando digo que as partes orientadas a objetos do Python parecem "aparafusadas", quero dizer que, às vezes, o lado da OOP parece bastante inconsistente. Veja o Ruby, por exemplo: no Ruby, tudo é um objeto e você chama um método usando a obj.methodsintaxe familiar (com exceção dos operadores sobrecarregados, é claro); no Python, tudo também é um objeto, mas alguns métodos você chama como função; ou seja, você sobrecarrega __len__para retornar um comprimento, mas chame-o usando, em len(obj)vez do mais familiar (e consistente) obj.lengthcomum em outros idiomas. Sei que há razões por trás dessa decisão de design, mas não gosto delas.

Além disso, o modelo OOP do Python não possui nenhum tipo de proteção de dados, ou seja, não há membros privados, protegidos e públicos; você pode imitá-los usando _e __na frente dos métodos, mas é meio feio. Da mesma forma, o Python também não entende bem o aspecto de passagem de mensagens do OOP.


17
O auto-parâmetro é apenas tornar explícito o que outros idiomas deixam implícito. Esses idiomas têm claramente um parâmetro "auto".

13
@ Roger Pate: Sim, mas essa necessidade explícita de "eu" é meio irritante (e, eu diria, uma abstração com vazamento). Também não surgiu como uma decisão deliberada de design, mas devido às regras de escopo "estranhas" do Python. Não consigo encontrar o artigo rapidamente, mas há uma postagem de e-mail de Guido van Rossum que explica muito bem por que o parâmetro "self" é necessário.
Mipadi 29/10/10

2
@ Roger Pate: nas linguagens orientadas a objetos, passar o destino como o primeiro parâmetro ainda pode ser considerado um detalhe de implementação. Meu argumento, porém, não é se é uma boa ideia ou não; o ponto é que, em Python, é não devido a uma decisão de design consciente, mas sim para contornar verrugas no sistema de escopo.
Mipadi 29/10/10

3
@ mipadi: A atualização tem um raciocínio melhor (então removo o voto negativo), mas se você vê o len como um operador que você sobrecarrega, é mais OO em Python. Gostaria de ver um exemplo ou raciocínio sobre como o Python interpreta errado a passagem de mensagens.

8
O eu explícito é uma conseqüência do fato de que os métodos são apenas funções (e, como Winston observou, declarações implícitas de variáveis ​​locais). Você é livre para não gostar dessa decisão de design, mas chamar o OOP de "aparafusado" em um idioma em que tudo é acessível como um objeto em tempo de execução é bobagem.
Ncoghlan

19

Coisas que não gosto no Python:

  1. Threading (eu sei que já foi mencionado, mas vale a pena mencionar em todos os posts).
  2. Não há suporte para funções anônimas de várias linhas ( lambdapode conter apenas uma expressão).
  3. A falta de uma simples, mas poderosa função de leitura de entrada / classe (como cinou scanfem C ++ e C ou Scannerem Java).
  4. Todas as strings não são unicode por padrão (mas corrigidas no Python 3).

5
Em relação a (2), acho que isso é compensado pela possibilidade de ter funções aninhadas.
Konrad Rudolph

3
@KonradRudolph Meu principal problema com funções aninhadas em vez de lambdas de várias linhas é que a ordem de leitura é trocada.
CookieOfFortune

2
@wkschwartz: raw_inpute 'sys.stdin' são bastante barebones. Eles não suportam a obtenção de entrada formatada (por exemplo, algo como "% d:% d:% d"% (hora, minuto, segundo) para ler a tempo). Até agora, o Python não tem nada parecido com a funcionalidade do scanf (em C) ou Scanner (Java).
MAK

2
@limscoder: todas as strings são unicode por padrão em Java. Não vejo uma boa razão para ter classes str e unicode separadas. IMHO, seqüências de caracteres e matrizes de bytes não devem ser representados pela mesma abstração. Uma classe de string deve ser para armazenar e manipular texto - cuja representação interna não nos interessa. Não devemos querer fazer coisas como truncar / substituir / excluir / inserir em um byte específico dentro de uma string - queremos fazer isso com um caractere específico . É fácil esquecer a distinção e fazer com que o seu código exploda quando alimentado com entrada em inglês.
MAK

1
@limscoder: se você quiser ver o unicode fácil, tente o Tcl. Eu tive que mudar de Tcl para Python alguns anos atrás, e cara, fiquei surpreso com a compatibilidade do suporte unicode do python primitivo. É verdadeiramente invisível no Tcl, e uma grande dor no python.
Bryan Oakley

18

Argumentos padrão com tipos de dados mutáveis.

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

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

Geralmente é o resultado de alguns erros sutis. Eu acho que seria melhor se ele criasse um novo objeto de lista sempre que um argumento padrão fosse necessário (em vez de criar um único objeto para usar em todas as chamadas de função).

Editar: não é um problema enorme, mas quando algo precisa ser referido nos documentos, geralmente significa que é um problema. Isso não deve ser necessário.

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

Especialmente quando esse deveria ter sido o padrão. É apenas um comportamento estranho que não corresponde ao que você esperaria e não é útil para um grande número de circunstâncias.


Vejo muitas reclamações sobre isso, mas por que as pessoas insistem em ter uma lista vazia (que a função modifica) como argumento padrão? Isso é realmente um problema tão grande? Ou seja, isso é um problema real ?
Martin Vilcans

8
Isso viola o princípio da menor surpresa. Não se esperaria que os parâmetros de uma função sobrevivessem entre as chamadas.
AIB

É uma conseqüência de ser uma linguagem de script. Você só ficará perplexo com esse bug UMA VEZ, e nunca mais. Descobrir esse bug por si mesmo realmente dá um chute na bunda para lembrá-lo de que sim, essa ainda é uma linguagem de script. E isso é apenas porque a linguagem é boa para ocultar o aspecto de script (supondo que você o use corretamente).
Zoran Pavlovic

@ZoranPavlovic por curiosidade, por que isso é uma conseqüência de ser uma linguagem de script? Parece ser um problema quando os dados são vinculados e porque as listas são mutáveis ​​(que são duas coisas que normalmente são boas, mas acabam sendo ruins quando combinadas). O mesmo problema pode ocorrer em uma linguagem sem scripts se você vincular os dados no momento da criação da função, em vez de criar uma nova lista sempre que a função for chamada.
jsternberg

@ib: Acho que não - o parâmetro aqui, como qualquer outro objeto Python - é um ponteiro para um objeto. Nesse caso, o objeto é mutável e a variável é vinculada quando a função é declarada. O parâmetro "sobrevive através de chamadas", mas o que sobrevive é a referência a um objeto mutável.
Patrick Collins

14

Alguns dos recursos do Python que o tornam tão flexível como uma linguagem de desenvolvimento também são vistos como grandes desvantagens daqueles usados ​​na análise estática do "programa inteiro", conduzida pelo processo de compilação e vinculação em linguagens como C ++ e Java.

  • Declaração implícita de variáveis ​​locais

Variáveis ​​locais são declaradas usando a declaração de atribuição comum. Isso significa que as ligações variáveis ​​em qualquer outro escopo exigem que a anotação explícita seja captada pelo compilador (declarações globais e não locais para escopos externos, notação de acesso a atributos para escopos de instância). Isso reduz enormemente a quantidade de clichê necessária durante a programação, mas significa que são necessárias ferramentas de análise estática de terceiros (como pyflakes) para executar verificações tratadas pelo compilador em linguagens que exigem declarações explícitas de variáveis.

  • "Monkey patching" é suportado

O conteúdo dos módulos, objetos de classe e até o espaço para nome interno pode ser modificado em tempo de execução. Isso é extremamente poderoso, permitindo muitas técnicas extremamente úteis. No entanto, essa flexibilidade significa que o Python não oferece alguns recursos comuns às linguagens OO de tipo estatístico. Mais notavelmente, o parâmetro "self" para métodos de instância é explícito e não implícito (como "métodos" não precisam ser definidos dentro de uma classe, eles podem ser adicionados posteriormente modificando a classe, o que significa que não é particularmente prático para passar a referência da instância implicitamente) e os controles de acesso ao atributo não podem ser facilmente aplicados com base no fato de o código estar "dentro" ou "fora" da classe (pois essa distinção existe apenas enquanto a definição da classe está sendo executada).

  • Longe do metal

Isso também se aplica a muitas outras linguagens de alto nível, mas o Python tende a abstrair a maioria dos detalhes de hardware. Linguagens de programação de sistemas como C e C ++ ainda são muito mais adequadas para lidar com o acesso direto ao hardware (no entanto, o Python conversará alegremente com aqueles por meio dos módulos de extensão CPython ou, de maneira mais portável, pela ctypesbiblioteca).


12
  1. Usando indentação para blocos de código em vez de {} / begin-end, qualquer que seja.
  2. Toda linguagem moderna mais recente tem escopo lexical adequado, mas não o Python (veja abaixo).
  3. Documentos caóticos (compare com a documentação do Perl5, que é excelente).
  4. Camisa de força (há apenas uma maneira de fazê-lo).

Exemplo para escopo quebrado; transcrição da sessão do intérprete:

>>> 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 nonlocalpalavras - chave foram introduzidas para corrigir essa estupidez de design.


2
com relação ao escopo, pode valer a pena para os curiosos olhar python.org/dev/peps/pep-3104 para entender o raciocínio do método atual.
Winston Ewert

Concorde com +1. Então, +1.
Jas

34
Ter uma maneira de fazer isso é uma vantagem. Ao ler o código de outra pessoa, você não decifra uma única declaração. Depois que os idiomas estiverem conectados em seu cérebro, você deverá ter reconhecimento instantâneo.
rox0r

9
Concordo totalmente com @ rox0r. A "camisa de força" evita todo tipo de guerra de sintaxe.
keithjgrant

8
Para ser sincero, raramente preciso das palavras-chave globalou nonlocalno Python. Tão raramente que esqueço que esse problema existe e tenho que voltar a pesquisá-lo nas poucas vezes em que surgiu, apesar do fato de eu escrever código Python todos os dias no trabalho. Para mim, código que precisa modificar variáveis ​​globais (ou pior, variáveis ​​não globais externas) é um cheiro de código. Geralmente, existe (nem sempre) uma maneira melhor.
24711 Ben

11

Acho a combinação de sintaxe orientada a objetos this.method()e procedural / funcional do python method(this)muito perturbadora:

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

Isso é particularmente ruim porque um grande número de funções (em vez de métodos) é apenas despejado no espaço de nomes global : métodos relacionados a listas, seqüências de caracteres, números, construtores, metaprogramação, todos misturados em uma grande lista alfabética.

No mínimo, linguagens funcionais como o F # têm todas as funções devidamente nomeadas em módulos:

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

Então eles não estão todos juntos. Além disso, esse é um padrão seguido em toda a biblioteca, pelo menos é consistente.

Eu entendo as razões para fazer a função vs coisa de método , mas ainda acho que é uma má idéia para misturá-los assim. Eu ficaria muito mais feliz se a sintaxe do método fosse seguida, pelo menos para as operações comuns:

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

Se os métodos estão mudando ou não, tê-los como métodos no objeto tem várias vantagens:

  • Local único para procurar as operações "comuns" em um tipo de dados: outras bibliotecas / etc. podem ter outras coisas sofisticadas que podem fazer com os tipos de dados, mas as operações "padrão" estão nos métodos do objeto.
  • Não é necessário continuar repetindo a Modulechamada Module.method(x). Tomando o exemplo funcional da lista acima, por que tenho que continuar dizendo Listrepetidamente? Deve saber que é um Liste não quero chamar a Navigation.map()função! O uso da x.map()sintaxe a mantém SECA e ainda não ambígua.

E, é claro, tem vantagens em relação à maneira de colocar tudo no espaço de nomes global . Não é que a maneira atual seja incapaz de fazer as coisas. É até bem conciso ( len(lst)), já que nada está no namespace! Entendo as vantagens de usar funções (comportamento padrão, etc.) sobre métodos, mas ainda não gosto.

É apenas bagunçado. E em grandes projetos, a bagunça é seu pior inimigo.


1
sim ... Eu realmente sinto falta do estilo LINQ (tenho certeza de que o LINQ não é o primeiro a implementá-lo, mas estou mais familiarizado com isso) de manipulação de lista.
CookieOfFortune

1
Não pense em len (x) como um método. "len" é uma função. Python tem funções e métodos e não vejo nada de errado com essa abordagem. A falta de funções adequadas é, geralmente, a fonte de muitas digitações desnecessárias.
precisa saber é

Eu sei que len()é uma função e quais são as vantagens. Eu também afirmou por isso que eu acho que é uma má idéia, porque eu acho que os globais funções são particularmente má idéia, e porque eu acho métodos fornecem um método conveniente de organizar e escopo a sua funcionalidade =)
Haoyi

Não acho que 42 (ou 43?) Palavras-chave seja um número "grande". Que também inclui coisas como def, classe outras chamadas não-funcionais. Compare isso com mais de 100 na maioria dos outros idiomas populares. Além disso, considere a linha do import this: Namespaces are one honking great idea -- let's do more of those!. Eu acho que você pode entender mal namespaces do Python;)
Wayne Werner

8

Falta de homoiconicidade .

O Python teve que esperar pelo 3.x para adicionar uma palavra-chave "with". Em qualquer idioma homoicônico, poderia ter sido adicionado trivialmente em uma biblioteca.

A maioria dos outros problemas que vi nas respostas são de um dos três tipos:

1) Coisas que podem ser corrigidas com ferramentas (por exemplo, pyflakes) 2) Detalhes da implementação (GIL, desempenho) 3) Coisas que podem ser corrigidas com padrões de codificação (ou seja, recursos que as pessoas desejam que não existam)

# 2 não é um problema com o idioma, IMO # 1 e # 3 não são problemas sérios.


1
withestava disponível a partir de Python 2.5 com from __future__ import with_statement, mas eu concordo, eu ocasionalmente achei lamentável que declarações como if/ for/ print/ etc são "especiais" em vez de funções regulares
DBR

7

Python é minha linguagem favorita, pois é muito expressiva, mas ainda evita que você cometa muitos erros. Eu ainda tenho algumas coisas que me incomodam:

  • Nenhuma função anônima real. O Lambda pode ser usado para funções de instrução única, e a withinstrução pode ser usada para muitas coisas em que você usaria um bloco de código no Ruby. Mas, em algumas situações, as coisas ficam um pouco mais desajeitadas do que teriam que ser. (Longe de ser tão desajeitado quanto seria em Java, mas ainda assim ...)

  • Alguma confusão na relação entre módulos e arquivos. A execução de "python foo.py" na linha de comando é diferente de "import foo". As importações relativas no Python 2.x também podem causar problemas. Ainda assim, os módulos do Python são muito melhores que os recursos correspondentes de C, C ++ e Ruby.

  • Explícito self. Embora eu entenda algumas das razões para isso, e mesmo que eu use o Python diariamente, eu cometo o erro de esquecê-lo. Outro problema é que se torna um pouco entediante transformar uma classe em um módulo. O eu explícito está relacionado ao escopo limitado do qual os outros se queixaram. O menor escopo no Python é o escopo da função. Se você mantiver suas funções pequenas, como deveria, isso não será um problema por si só e o IMO geralmente fornecerá um código mais limpo.

  • Algumas funções globais, como len, que você esperaria ser um método (que na verdade é nos bastidores).

  • Recuo significativo. Não é a ideia em si, que eu acho ótima, mas como essa é a única coisa que impede tantas pessoas de experimentar o Python, talvez o Python seja melhor com alguns símbolos de início / fim (opcionais). Ignorando essas pessoas, eu também poderia viver totalmente com um tamanho obrigatório para o recuo.

  • Que não é o idioma interno dos navegadores da web, em vez do JavaScript.

Dessas reclamações, é apenas a primeira com a qual me preocupo o suficiente, e acho que deve ser adicionada ao idioma. Os outros são bem menores, exceto o último, o que seria ótimo se isso acontecesse!


+1 Isso me faz pensar se escrever datetime.datetime.now()quando um projeto pode escrever datetime.nowe, em seguida, misturar dois projetos de uma maneira exclui a outra e certamente isso não teria acontecido em Java, que não nomearia um módulo como um arquivo (?) se você vê como o modo comum parece confundir o módulo com o arquivo quando ambos os usos são praticados e explícitos self, ainda tento entender, pois as chamadas não têm o mesmo número de argumentos que as funções. E você pode pensar que o python da VM possui é lento?
Niklas Rosencrantz

Em relação ao seu problema com a palavra-chave auto explícita. Posso sugerir o uso de um bom IDE python para isso? Eu sei que o PyDev no Eclipse preenche automaticamente a parte auto de uma assinatura de função se detectar que você está escrevendo dentro de uma classe.
Zoran Pavlovic

5

O Python não está totalmente maduro: a linguagem do python 3.2 atualmente tem problemas de compatibilidade com a maioria dos pacotes atualmente distribuídos (normalmente eles são compatíveis com o python 2.5). Essa é uma grande desvantagem que atualmente exige mais esforço de desenvolvimento (encontre o pacote necessário; verifique a compatibilidade; pese escolhendo um pacote não tão bom que possa ser mais compatível; obtenha a melhor versão, atualize-a para 3,2, o que pode levar dias; comece a fazer algo útil).

Provavelmente, em meados de 2012, isso será menos uma desvantagem.

Note que eu acho que fui votado por um fã-boy. Durante uma discussão com desenvolvedores, nossa equipe de desenvolvedores de alto nível chegou à mesma conclusão.

A maturidade, em um sentido principal, significa que uma equipe pode usar a tecnologia e estar em funcionamento muito rapidamente, sem riscos ocultos (incluindo problemas de compatibilidade). Pacotes python de terceiros e muitos aplicativos não funcionam na versão 3.2 para a maioria dos pacotes hoje. Isso cria mais trabalho de integração, teste, reimplementação da própria tecnologia, em vez de resolver o problema em questão == tecnologia menos madura.

Atualização para junho de 2013: Python 3 ainda tem problemas de maturidade. De vez em quando, um membro da equipe menciona um pacote necessário e diz "exceto que é apenas para 2.6" (em alguns desses casos, eu implementei uma solução alternativa via soquete localhost para usar o pacote somente para 2.6 com 2.6 e o ​​restante de nossas ferramentas ficam com 3.2). Nem o MoinMoin, o wiki em python puro, é escrito em Python 3.


2
Eu concordo com você somente se sua definição de maturidade não for compatível com uma versão incompatível por design .
tshepang

3
Concordo que os dois fluxos incompatíveis do python são um problema (embora compreensível o porquê disso), mas não vejo isso como um problema de "maturidade".
Winston Ewert

A maturidade, em um sentido, significa que uma equipe pode usar a tecnologia e estar em funcionamento muito rapidamente, sem riscos ocultos (incluindo problemas de compatibilidade). Pacotes python de terceiros e muitos aplicativos não funcionam na versão 3.2 para a maioria dos pacotes hoje. Isso cria mais trabalho de integração, teste, reimplementação da própria tecnologia, em vez de resolver o problema em questão == tecnologia menos madura.
Jonathan Cline IEEE

2
Em seguida, basta usar o Python 2.x. Você sabe ... a versão que todo mundo está usando. Ou leia a documentação dos pacotes por 2 segundos para descobrir com quais versões ele é compatível.
Jsternberg

2
"Só porque o python 3.0 foi lançado há algum tempo não significa que seja a versão que você deve usar. Python 3.0 e 2.x estão sendo desenvolvidos ao mesmo tempo. Espero que, no futuro, todos possamos usar python 3.0, mas por enquanto usar o 2.x é uma boa solução "-> Essa é uma maneira de dizer 500 caracteres: ainda não está madura.
Jonathan Cline IEEE

4

O escopo do Python está muito quebrado, o que torna a programação orientada a objetos no Python muito estranha.


8
Você pode dar um exemplo? (Eu tenho certeza que você está certo, mas eu gostaria de um exemplo)
Winston Ewert

24
Eu gosto de Python, mas eu absolutamente desprezo ter que colocar self.na frente de todas as referências a uma propriedade e método de instância. Torna impossível usar o Python para criar uma DSL, como é tão fácil de fazer no Ruby.
Adam Crossland

35
Não acho o eu estranho, gosto da explicitação.
Winston Ewert

9
Não vejo qual é a grande importância do eu explícito. Em C ++, Java e D, as pessoas geralmente tornam variáveis ​​de membros explícitas por convenção de qualquer maneira, por exemplo, prefixando-as com um sublinhado.
dsimcha

7
Você usa self em métodos diferentes da declaração: def foo (self) mas self.foo (). Acho essa mistura de definição explícita, mas coisas implícitas nos bastidores não muito bonitas.
LennyProgrammers

4

Minhas queixas sobre Python:

  • OOP aparafusado (Veja a resposta de @ mipadi para elaboração deste)
  • Implementação interrompida de lambdas
  • Questões de escopo
  • Nenhuma coleção persistente na biblioteca padrão
  • Má acessibilidade a DSLs incorporadas

Por que o voto negativo?
missingfaktor

Não sou a favor do voto negativo, mas você pode explicar por que acha que o OO está preso? O Python sempre teve OO, é uma parte essencial da linguagem.
Daenyth 15/07/11

Veja a resposta de @ mipadi.
missingfaktor


4

Os modificadores de acesso no Python não são aplicáveis ​​- dificultam a criação de códigos modularizados e bem estruturados.

Suponho que isso faça parte do escopo quebrado da @ Mason - um grande problema em geral com esse idioma. Para o código que deveria ser legível, parece bastante difícil descobrir o que pode e deve estar no escopo e qual será o valor em um determinado momento - atualmente, estou pensando em mudar da linguagem Python por causa desses inconvenientes. .

Só porque "todos nós somos adultos concordantes" não significa que não cometemos erros e não trabalhemos melhor dentro de uma estrutura sólida, especialmente quando se trabalha em projetos complexos - indentação e sublinhados sem sentido não parecem suficientes .


Portanto, a falta de controles de acesso é ruim ... mas o escopo explícito de gravações de variáveis ​​em qualquer espaço de nome não local também é ruim?
Ncoghlan

@ncoghlan: 1 - esse recurso é padrão em muitos idiomas modernos, dependendo de como você configura seu projeto. 2 - Está sob o controle do programador. 3 - não sei o que há de tão bom nisso - você pode controlar facilmente seu escopo com algumas configurações de projeto na maioria dos idiomas / IDEs compilados. Se 'somos todos adultos concordantes', poderemos tomar nossas próprias decisões e ajustar o escopo de acordo com nosso nível de conforto específico.
Vector

2
O problema é que as pessoas que solicitam "controles de acesso forçados" estão nos pedindo para fazer uma das coisas que tornam o Python uma linguagem de cola tão boa: é deliberadamente difícil para os desenvolvedores controlar como seu código será usado posteriormente. Quanto do padrão nos padrões C ++ e Java existe apenas para solucionar os controles de acesso impostos? Definitivamente, consigo entender as pessoas que optam por não usar o Python por esses motivos, mas a imposição estática nunca substituirá testes rigorosos.
Ncoghlan

1
@ncoghlan - para mim, as grandes coisas sobre Python são a elegância da sintaxe e da sucessão - a expressividade. E como eu disse, o escopo tem menos a ver com os programadores que mexem com coisas que não deveriam do que com a estrutura e a organização do código - então o conceito de 'consentir adultos' é discutível. Trabalho em projetos complexos, não em utilitários e scripts simples - o código deve ser cuidadosamente modularizado e estruturado - os modificadores de acesso são uma das maneiras mais importantes de garantir isso.
Vector

1
E revisão de código, treinamento e análise de acoplamento são outros. Para mim, os controles de acesso impostos se enquadram no mesmo balde da digitação estática: eles ajudam a fornecer mais confiança na correção (mas não o suficiente para evitar a necessidade de testes extensivos), mas com um alto custo na produtividade do desenvolvimento. (Em um nível prático, os controles de acesso aos atributos de classe também não se encaixam no modelo de objeto do Python, onde os métodos são apenas funções comuns recuperadas das classes. O limite "dentro / fora" das classes não existe realmente, portanto não pode ser. )
ncoghlan

3
  1. O desempenho não é bom, mas está melhorando com o pypy,
  2. O GIL impede o uso de threading para acelerar o código (embora isso geralmente seja uma otimização prematura),
  3. Só é útil para programação de aplicativos,

Mas tem alguns ótimos recursos redentores:

  1. É perfeito para a RAD,
  2. É fácil interagir com C (e para C incorporar um intérprete python),
  3. É muito legível,
  4. É fácil aprender,
  5. Está bem documentado,
  6. As baterias estão realmente incluídas, sua biblioteca padrão é enorme e o pypi contém módulos para praticamente tudo,
  7. Tem uma comunidade saudável.

O que inspirou a mencionar as vantagens? A questão para os problemas. Enfim, o que você quer dizer com útil apenas para programação de aplicativos? Que outra programação existe? O que especificamente não é bom?
tshepang

5
Listei as vantagens porque acho que superam os contras. Você já tentou implementar um módulo do kernel Linux em python.
dan_waterworth

3

Eu sou a favor do python e a primeira desvantagem que me vem à cabeça é que, ao comentar uma declaração como essa if myTest():, você deve alterar a indentação de todo o bloco executado que você não teria a ver com C ou Java. De fato, em python, em vez de comentar uma cláusula if, comecei a comentá-la desta maneira: `if True: #myTest (), portanto não precisarei alterar o seguinte bloco de código. Como Java e C não contam com indentação, torna mais fácil comentar declarações com C e Java.


1
Você editaria seriamente o código C ou Java para alterar o nível do bloco de algum código sem alterar seu recuo?
24711 Ben

4
@ Ben Temporariamente, sim ...
alternativa

1
@ Ben mesmo aqui.
Christopher Mahan

2
Eu uso o truque de mudar if something()para if False and something(). Outro truque é "comentar" usando uma string de várias linhas.
Martin Vilcans

1
@ Martin Claro! if False ... #
4928 Christopher Mahan

3

O despacho múltiplo não se integra bem ao sistema do tipo de despacho único estabelecido e não tem muito desempenho.

O carregamento dinâmico é um grande problema em sistemas de arquivos paralelos em que a semântica do tipo POSIX leva a lentidão catastrófica para operações com uso intenso de metadados. Tenho colegas que gastaram um quarto de milhão de horas-núcleo apenas carregando o Python (com numpy, mpi4py, petsc4py e outros módulos de extensão) carregados em núcleos de 65k. (A simulação produziu resultados científicos novos e significativos, por isso valeu a pena, mas é um problema quando mais de um barril de petróleo é queimado para carregar o Python uma vez.) A incapacidade de vincular estaticamente nos forçou a fazer grandes contorções para obter tempos de carregamento razoáveis ​​em escala, incluindo o patch libc-rtld para fazer o dlopenacesso coletivo ao sistema de arquivos.


Uau, parece altamente técnico, você tem algum material de referência, exemplos, posts ou artigos sobre o assunto? Gostaria de saber se posso ser exposto a esses casos em um futuro próximo.
vincent

Aron deu uma palestra no SciPy 2012 . O dlopenmaterial está na nossa biblioteca de collfs . Esse repositório também contém truques de zipimport adicionais inspirados no cache de caminho de Asher Langton. Estamos trabalhando em uma melhor distribuição e um artigo.
Jed

3
  • um monte de bibliotecas e softwares de terceiros muito populares que são amplamente utilizados, não são pitonicos. Alguns exemplos: soaplib, openerp, reportlab. A crítica está fora do escopo, está lá, é amplamente usada, mas torna a cultura python confusa (prejudica o lema que diz: "Deveria haver uma - e de preferência apenas uma - maneira óbvia de fazê-lo"). Sucessos pitônicos conhecidos (como django ou trac) parecem ser a exceção.
  • a profundidade potencialmente ilimitada da abstração da instância, classe, metaclasse é conceitualmente bonita e única. Mas para dominá-lo, você precisa conhecer profundamente o intérprete (em que ordem o código python é interpretado etc.). Não é amplamente conhecido e usado (ou usado corretamente), enquanto magia negra semelhante, como os genéricos C #, conceitualmente mais complicada (IMHO) parece mais amplamente conhecida e usada proporcionalmente.
  • Para obter uma boa compreensão do modelo de memória e de encadeamento, é necessário ter bastante experiência com python, porque não há especificações abrangentes. Você apenas sabe o que funciona, talvez porque você leu as fontes do intérprete ou peculiaridades experientes e descobriu como corrigi-las. Por exemplo, existem apenas referências fortes ou fracas, não as referências suaves e fantasmas do java. Java possui um encadeamento para coleta de lixo, enquanto não há resposta formal sobre quando a coleta de lixo ocorre em python; você pode apenas observar que a coleta de lixo não ocorre se nenhum código python for executado e concluir que provavelmente está acontecendo algumas vezes ao tentar alocar memória. Pode ser complicado quando você não sabe por que um recurso bloqueado não foi lançado (minha experiência sobre isso foi mod_python no freeswitch).

De qualquer forma, python é minha língua principal há 4 anos. Ser fanboys, elitistas ou monomaníacos não faz parte da cultura python.


+1. As especificações para o modelo de memória e encadeamento estão ativadas. Mas o FWIW, o coletor de lixo Java estar em um encadeamento (e quase tudo no GC) não é um aspecto da linguagem Java ou das especificações da VM em si, mas é um problema da implementação de uma JVM específica. No entanto, a principal JVM da Sun / Oracle é amplamente documentada no comportamento e na configuração do GC, na medida em que existem livros completos publicados sobre o ajuste da JVM. Em teoria, é possível documentar o CPython da mesma maneira, independentemente da especificação da linguagem.
precisa

2
  • OOP estranho:
    • len(s)através __len__(self)e outros "métodos especiais"
    • métodos especiais extras que podem ser derivados de outros métodos especiais ( __add__e __iadd__para +e +=)
    • self como primeiro parâmetro do método
    • você pode esquecer de chamar o construtor da classe base
    • sem modificadores de acesso (privado, protegido ...)
  • sem definições constantes
  • sem imutabilidade para tipos personalizados
  • GIL
  • baixo desempenho que leva a uma mistura de Python e C e problemas com as compilações (procurando bibliotecas C, dependências de plataforma ...)
  • documentação ruim, especialmente em bibliotecas de terceiros
  • incompatibilidade entre Python 2.xe 3.x
  • ferramentas de análise de código ruins (em comparação com o que é oferecido para linguagens estaticamente tipadas, como Java ou C #)

5
Pessoalmente, acho que a incompatibilidade entre 2.x e 3.x é uma das maiores vantagens do Python. Claro, também é uma desvantagem. Mas a audácia dos desenvolvedores de quebrar a compatibilidade com versões anteriores também significa que eles não precisavam carregar crosta continuamente. Mais idiomas precisam dessa revisão.
precisa saber é o seguinte

0

"Imutabilidade" não é exatamente o ponto forte. Os números, tuplas e cordas AFAIK são imutáveis, todo o resto (ou seja, objetos) é mutável. Compare isso com linguagens funcionais como Erlang ou Haskell, onde tudo é imutável (por padrão, pelo menos).

No entanto, a imutabilidade realmente brilha com a simultaneidade *, que também não é o ponto forte do Python, pelo menos é consequente.

(* = Para os nitpickers: quero dizer simultaneidade que é pelo menos parcialmente paralela. Acho que o Python está bem com simultaneidade "single-threaded", na qual a imutabilidade não é tão importante. (Sim, amantes de FP, eu sei que a imutabilidade é ótimo mesmo sem simultaneidade.))


0

Eu adoraria ter construções explicitamente paralelas. Frequentemente, quando escrevo uma lista de compreensão como

[ f(x) for x in lots_of_sx ]

Não ligo para a ordem em que os elementos serão processados. Às vezes, eu nem me importo com a ordem em que elas são devolvidas.

Mesmo que o CPython não possa fazê-lo bem quando meu f é puro Python, um comportamento como esse pode ser definido para outras implementações usarem.


// gera um monte de threads // passa a fila da fila para todos os threads que.extend ([x para x em lotes_de_sx]) que.wait () # Aguarde o processamento de todos os lotes_de_sx por segmentos.
Zoran Pavlovic

0

O Python não possui otimização de chamada de cauda, ​​principalmente por razões filosóficas . Isso significa que a recursão final em estruturas grandes pode custar memória O (n) (devido à pilha desnecessária mantida) e exigirá que você reescreva a recursão como um loop para obter memória O (1).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.