Exemplos concretos da máxima "única maneira de fazê-lo" do Python [fechado]


34

Estou aprendendo Python e estou intrigado com o seguinte ponto no PEP 20 The Zen of Python :

Deve haver uma - e preferencialmente apenas uma - maneira óbvia de fazê-lo. Embora esse caminho possa não ser óbvio a princípio, a menos que você seja holandês.

Alguém poderia oferecer exemplos concretos dessa máxima? Estou particularmente interessado no contraste com outros idiomas, como Ruby. Parte da filosofia de design do Ruby (originária do Perl, eu acho?) É que várias maneiras de fazer isso são uma coisa boa. Alguém pode oferecer alguns exemplos mostrando os prós e contras de cada abordagem. Note, não estou buscando uma resposta para a qual é melhor (que provavelmente é subjetiva demais para ser respondida), mas uma comparação imparcial dos dois estilos.

Respostas:


47

Comparado a linguagens como Perl, o Python possui um número limitado de construções de controle:

  • somente ife não unless,
  • apenas forque itera sobre sequências e não foreachou no estilo C for,
  • apenas whileque verifica uma condição a cada loop e não do-while,
  • somente if-elife não switch,
  • há apenas um construto de comentário, o #, e para cada linha, você pode dizer se é comentado ou não, sem olhar para as linhas anteriores.

Além disso, há quase uma maneira de recuar sua fonte; a maioria dos casos de recuo criativo é sintaticamente excluída.

Isso facilita a análise de uma fonte Python para humanos.

Há tentativas de ser mínimo, mas completo, nos tipos internos e na biblioteca padrão.

  • para lista mutável, você usa o único listtipo interno; é O (1) para a maioria das operações, e você nunca precisa escolher a implementação correta,
  • para listas imutáveis, igualmente, você apenas usa o tupletipo,
  • para mapas, você usa o único built-in dictque é extremamente eficiente na maioria dos casos, sem necessidade de ponderar qual implementação usar.

O Python 3 estende isso para números inteiros: não importa o tamanho do seu número inteiro, você usa o mesmo tipo e nunca se importa com coerção.

Python tenta evitar o açúcar sintático. Mas às vezes adiciona açúcar sintático apenas para tornar óbvio o caminho óbvio. Você pode escrever em if foo is not Nonevez de if not (foo is None)porque 'is not' é especial. Ainda foo is not Nonelê com facilidade, não pode ser mal interpretado, e você não precisa pensar, basta escrever a coisa óbvia.

Obviamente, a maioria das coisas mais complexas no Python pode ser feita de várias maneiras. Você pode adicionar métodos às classes por declaração ou por simples atribuição de slot, pode passar argumentos para funções de várias maneiras criativas, etc. Isso ocorre apenas porque os elementos internos do idioma são expostos principalmente.

A chave é que sempre existe uma maneira de se tornar a melhor, o caso de cobertura total. Se existirem outras formas, elas não foram adicionadas como alternativas iguais (como ife unless), mas apenas expõem o funcionamento interno. Lenta mas firmemente, essas alternativas são obsoletas (não eliminadas!), Aprimorando o melhor mecanismo conhecido.

Decoradores agrupam chamadas de função AOP. Antes da versão 2.6, você tinha que usar o __metaclass__membro mágico para declarar a metaclasse de uma classe; agora você também pode usar a mesma sintaxe do decorador. Antes do 3.0, você tinha dois tipos de strings, orientados a bytes e Unicode, que você pode misturar inadvertidamente. Agora você tem o único Unicode stre o único binário transparente bytes, que não pode ser misturado por engano.


3
Apenas como uma nota, não esqueça de """comentários (docstrings). Estes abrangem várias linhas.
asthasr

8
Literais de aspas triplas são apenas cadeias de caracteres, o mesmo que aspas simples, mas podem se estender por várias linhas sem sair do final da linha. Uma literal de sequência logo após a declaração é considerada uma sequência de documentos, e não é um comentário, geralmente é acessível como __doc__atributo. Mas cordas é uma área onde Python definitivamente fornece muitos caminhos retos ': uso de aspas simples, duplo ou triplo, juntar-se implicitamente literais adjacentes, uso rde literais-primas, etc.
9000

1
Eu acho que @ o comentário de syrion foi sobre o "você sempre pode decidir se uma linha é comentada ou não por apenas olhando para ele", o que não é verdade, porque de """ strings.
blubb

2
"Isso facilita a análise de uma fonte Python para humanos". <- isso é subjetivo
jiggy

Como a declaração da metaclasse mudou no 2.7? Não é possível encontrar o padrão decorador nos 2,7 documentos para metaclasses.
Nick T

10

Outros exemplos são:
len()é uma função em vez de um método presente em todas as seqüências; se você comparar com Java você tem .length, .size(), .getSize(), e outros métodos para encontrar o número de elementos em uma seqüência.

Outro exemplo é o fato de que .join()é um stringmétodo, não um método presente em todas as seqüências. Você não precisa saber se o parâmetro join é uma lista, um conjunto, uma compreensão ou o que quer que seja.


8

Em C, existem muitas maneiras possíveis de aumentar o valor de uma variável em um:

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

Cada termina-se o aumento do valor de ipelo 1, mas cada um deles é ligeiramente diferente.

No Python, existe realmente apenas uma maneira; basta adicionar um.

i += 1

E embora haja mais de uma maneira sintaticamente válida de fazer isso (por exemplo i = i + 1), você está fazendo a mesma coisa com os mesmos efeitos colaterais.


1
Não sou especialista, mas esse exemplo parece violar precisamente a idéia "única maneira de fazê-lo". Temos duas maneiras de fazer isso, mas qual é a mais óbvia? A meu ver, o primeiro exemplo é mais óbvio, enquanto o segundo é um pouco mais conciso, mas não menos legível ou óbvio para qualquer programador que progrediu além do básico. Obrigado pela sua resposta - é um bom alimento para pensar.
Charles Roper

@ Peter (e @Charles): Na verdade, i = i + 1é uma atribuição, não um incremento. Em python, um incremento é i += 1. Em linguagens de estilo C você pode escrever i++, ++ie i += 1.
27411 Josh K

2
Não tenho certeza sobre o seu comentário "muita confusão", todos os três exemplos de C (você perdeu i += 1, BTW) produzem exatamente o mesmo resultado. A única vez em que vejo pessoas confusas é quando elas pré ou pós-incrementam uma variável como parte de uma expressão maior, e isso geralmente é rapidamente corrigido lendo a seção apropriada da referência de idioma. Pessoalmente, eu teria escolhido no fato de que você pode se referir ao quinto caracter de uma string por ambos str[4]ou *(str+4), mas talvez isso foi muito fácil ...
TMN

2
@ TMN: alguns casos, como max(i++, ++i)não podem ser rapidamente corrigidos. C tem muitos casos de comportamento "indefinidos" e "dependentes da implementação", todos por uma boa razão - mas cada um pode criar uma armadilha.
9000

@TMN: para não mencionar 4 [str] (válido em C, pode não ser válido em C ++).
Vatine 28/07

6

Outra possibilidade pode ser a compreensão da lista. No Python, você pode fazer isso:

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

Mas a maneira "óbvia" (se você é holandês ou está mais familiarizado com o Python) de fazer isso seria com uma compreensão da lista:

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

É mais curto, a new_list é criada em uma etapa, é mais rápida, acredito, e é elegante. Por outro lado, alguém poderia argumentar que parece menos explícito, mas acho que, depois que você se acostuma, é igualmente explícito.


Para indentação e código: acrescente 4 espaços e respeite a indentação.
Inca
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.