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)
fonte
Respostas:
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:
É 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.
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.
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.
Está longe do metal. Precisa escrever primitivas de encadeamento ou código do kernel ou algo assim? Boa sorte.
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.
A documentação não é tão boa quanto linguagens como PHP e Java que têm fortes bases corporativas.
fonte
with
instrução ou métodos em alist
. Qualquer coisa abordada no tutorial é basicamente impossível de pesquisar. Tenho uma sorte muito melhor com a documentação da Microsoft para C ++.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:
var
elet
. Se eu escrever em uma variável não declarada por nenhuma delas, o Python deve gerar um erro. Além disso,let
declara variáveis como somente leitura, enquantovar
variáveis são "normais".Considere este exemplo:
Observe que os tipos ainda estão implícitos (mas as
let
variáveis são digitadas estaticamente para todos os efeitos, pois não podem ser recuperadas para um novo valor, enquanto asvar
variá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:Isso pode ser substituído por um idioma ligeiramente diferente:
fonte
use strict;
euse warnings;
perl em um script de qualquer tamanho. O Python retirou o desenvolvedor de muitos auxiliares de depuração.var
elet
(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__
). Digaimport strict
,. Isso não vai acontecer, porém, uma vez que requer hackers sintáticos ...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 .
fonte
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.
fonte
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.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.method
sintaxe 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, emlen(obj)
vez do mais familiar (e consistente)obj.length
comum 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.fonte
Coisas que não gosto no Python:
lambda
pode conter apenas uma expressão).cin
ouscanf
em C ++ e C ouScanner
em Java).fonte
raw_input
e '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).Argumentos padrão com tipos de dados mutáveis.
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.
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.
fonte
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.
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.
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).
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
ctypes
biblioteca).fonte
Exemplo para escopo quebrado; transcrição da sessão do intérprete:
global
enonlocal
palavras - chave foram introduzidas para corrigir essa estupidez de design.fonte
global
ounonlocal
no 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.Acho a combinação de sintaxe orientada a objetos
this.method()
e procedural / funcional do pythonmethod(this)
muito perturbadora: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:
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:
Se os métodos estão mudando ou não, tê-los como métodos no objeto tem várias vantagens:
Module
chamadaModule.method(x)
. Tomando o exemplo funcional da lista acima, por que tenho que continuar dizendoList
repetidamente? Deve saber que é umList
e não quero chamar aNavigation.map()
função! O uso dax.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.
fonte
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 =)def
,class
e outras chamadas não-funcionais. Compare isso com mais de 100 na maioria dos outros idiomas populares. Além disso, considere a linha doimport this
:Namespaces are one honking great idea -- let's do more of those!
. Eu acho que você pode entender mal namespaces do Python;)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.
fonte
with
estava disponível a partir de Python 2.5 comfrom __future__ import with_statement
, mas eu concordo, eu ocasionalmente achei lamentável que declarações comoif
/for
/print
/ etc são "especiais" em vez de funções regularesPython é 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
with
instruçã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!
fonte
datetime.datetime.now()
quando um projeto pode escreverdatetime.now
e, 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ícitosself
, 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?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.
fonte
O escopo do Python está muito quebrado, o que torna a programação orientada a objetos no Python muito estranha.
fonte
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.Minhas queixas sobre Python:
fonte
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 .
fonte
Mas tem alguns ótimos recursos redentores:
fonte
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.fonte
if something()
paraif False and something()
. Outro truque é "comentar" usando uma string de várias linhas.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
dlopen
acesso coletivo ao sistema de arquivos.fonte
dlopen
material 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.De qualquer forma, python é minha língua principal há 4 anos. Ser fanboys, elitistas ou monomaníacos não faz parte da cultura python.
fonte
len(s)
através__len__(self)
e outros "métodos especiais"__add__
e__iadd__
para+
e+=
)self
como primeiro parâmetro do métodofonte
"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.))
fonte
Eu adoraria ter construções explicitamente paralelas. Frequentemente, quando escrevo uma lista de compreensão como
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.
fonte
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).
fonte