Python interessante e útil

Eu tenho programado em python há vários anos, no entanto, recentemente percebi que muitos truques úteis e momentos interessantes me passaram, talvez eu não seja o único, então decidi listá-los aqui, espero que esses truques sejam úteis para alguém no trabalho ou me façam conhecer um ao outro com essa linguagem mais perto.

Como em muitos idiomas em python, 1 é equivalente a True e 0 é False, ou seja,

1 == True. 

Parece, e o que há de errado nisso? No entanto, isso tem alguns efeitos colaterais associados ao fato de que os mesmos objetos devem ter os mesmos hashes, portanto, você não poderá amontoar a chave 1 e True em um dicionário.

  >>> a = {1: "one", 0: "zero", True: "true", False: "false"} # -> {1: 'true', 0: 'false'} 

Também permite as seguintes operações:

  >>> print(2 * False + True) # -> 1 

Neste exemplo, as cadeias de caracteres foram usadas como valores de dicionário, no entanto, muitas vezes eu quero usá-las como chaves de dicionário, sempre fiquei chateado que ao criar um dicionário usando chaves, você precisa especificar as cadeias entre aspas, gostaria de omiti-las, isso é possível se você criar dicionário através do construtor dict ().

  >>> {"one": 1, "two": 2, "three": 3} == dict(one=1, two=2, three=3) # -> True 

Além disso, não apenas os dicionários, mas também os conjuntos (conjunto) são criados usando chaves.

  >>> a = {1, 2, 3} 

Para combinar os dois conjuntos, por algum motivo, quero usar o operador +, provavelmente devido à maneira como as seqüências de caracteres são concatenadas. No entanto, o python não suporta esse operador para conjuntos. Mas é claro que isso não significa que sempre precisamos usar funções, os criadores abordaram esse problema de forma mais sistemática e adicionaram suporte para operações básicas em conjuntos (não apenas uniões) à linguagem e os "penduraram" em operadores lógicos .

 a = {1, 2, 3} b = {0, 2, 4} print(a & b) # -> {2} print(a | b) # -> {0, 1, 2, 3, 4} print(a ^ b) # -> {0, 1, 3, 4} print(a - b) # -> {1, 3},    #     

Continuando a conversa sobre dicionários, a partir da versão 3.7, a especificação do idioma garante que os dicionários preservem a ordem de inserção dos elementos. O OrderedDict não é mais necessário.

www.python.org/downloads/release/python-370
mail.python.org/pipermail/python-dev/2017-December/151283.html

 d = dict(zero='Cero', one='Uno', two='Dos', three='Tres', four='Cuatro', five='Cinco', six='Seis', seven='Siete', eight='Ocho', night='Nueve') for index, (key, value) in enumerate(d.items()): print(f"{index} is {key} in England and {value} in Spain") 

Preste atenção à linha de saída, ela começa com o prefixo f - este é um tipo especial de linhas introduzidas no python 3.6 .

Existem três tipos de strings no idioma: regular, indicado por aspas sem prefixos, bruto \ não processado (bruto), no qual caracteres especiais, como \ n, não são processados ​​e inseridos como texto e linhas f.

Eles foram criados para simplificar a saída, o python suporta um grande número de métodos de saída:

 print("result" + str(2)) #   , python   #      #  ,     print("result", 2) # print      , #        , #        , #      print("result %d" % 2) # %-,      C. print("result %d %.2f" % (2, 2)) # https://docs.python.org/3.4/library/string.html#formatspec print("result %(name)s" % {"name": 2}) #      print("{}".format(2)) #      format() #       print("{0} {1} {0}".format(1, 2)) #          #     #     #        ,    print("{} {}".format(2)) # -> IndexError: tuple index out of range print("{0} {0}".format(2, 3)) # -> 2 2       #     from math import pi #         print("{:.2f}".format(pi)) # -> 3.14 from string import Template #      s = Template("result $res") #       print(s.substitute(res = [3, 4])) 

Agora adicionado mais e f-lines. Todas as variáveis ​​do escopo estão disponíveis, você pode chamar funções, obter elementos por chave e, além disso, eles suportam cadeias de caracteres de formato.

 from math import pi result = 4 name = "user" print(f"{name:84s} pi= {pi:.2f}, result={result}, {name[2]}") # -> user pi= 3.14, result=4, e from datetime import datetime print(f"{datetime.now():%Y:%m-%d}") 

Eles são mais rápidos que todos os outros métodos de saída; portanto, se o python3.6 estiver disponível, é recomendável usá-los.

Uma das peças mais legais do python - não objetos e primitivos são compactados e descompactados, mas parâmetros e coleções.

 def func(*argv, **kwargs) 

No entanto, há uma falha de arquitetura na implementação:

  • argv - uma tupla, seus valores não podem ser alterados, valores não podem ser adicionados ou excluídos
  • O kwargs é um dicionário mutável, portanto, o cache não é possível

A desvantagem, é claro, não é grande, mas ainda é desagradável que você não possa transferir kwargs diretamente para um cache baseado em dicionário; por outro lado, se você adicionar uma lista a uma tupla, essa tupla também não poderá ser adicionada ao dicionário.

Os conjuntos também são criados com base em uma tabela de hash, o que significa que os valores devem ser hash; além disso, o conjunto em si é do tipo mutável e sem hash; existe um tipo especial de frozenset - um conjunto imutável (não me pergunte por que é necessário).

Eles discutiram a criação do tipo frozendict, mas ainda não o adicionaram (embora ele já tenha pelo menos um aplicativo - como kwargs). Para um dicionário imutável, o nomeduplo deve ser estufado. E também para anotações e aulas despretensiosas.

Quem em seus anos escolares escreveu ciclos para exibir os valores da matriz e ficou furioso com a vírgula no final, cada vez que ele decidia pontuar ou reescrever para ser bonito, e somente no curso 2-3 ele aprendeu sobre o método de junção? Ou eu sou o único?

Um dos recursos desagradáveis ​​do método join para strings é que ele funciona apenas com elementos de string, se a coleção tiver pelo menos uma não string, você precisará usar uma expressão de gerador, o que parece uma solução muito complicada para uma tarefa tão simples; no entanto, existe uma maneira de simplificar a saída dos valores da lista (sem colchetes) .

 a = list(range(5)) print(" ".join(a)) # -> TypeError: sequence item 0: expected str instance, int found print(" ".join(str(i) for i in a)) # -> 0 1 2 3 4 print(*a) # -> 0 1 2 3 4 

Como as strings também são coleções, elas também podem ser "unidas".

 print('-'.join("hello")) # -> hello 

Considere a linha do exemplo anterior.

 print(" ".join(str(i) for i in a)) # -> 0 1 2 3 4 

A expressão do gerador é passada para a função de junção sem colchetes; os parênteses podem ser omitidos para simplificar a leitura do código. Python cuida da expressividade.

 print(sum(i**2 for i in range(10))) # -> 285 

Além disso, os parênteses podem ser omitidos ao criar tuplas:

 article = "python", 2018, "LinearLeopard" #   theme, year, author = "python", 2018, "LinearLeopard"#   theme, year, _ = "python", 2018, "LinearLeopard" #     #    # ,  , #  -   , #    #  theme, _, _ = "python", 2018, "LinearLeopard" #    theme, *, author = "python", 2018, "LinearLeopard" #    # ,   #  , # ,  #   #   

O asterisco também pode ser usado em declarações de função, para que você possa criar parâmetros que podem ser especificados apenas por chave .

 def sortwords(*wordlist, case_sensitive=False): 

Você pode passar quantos parâmetros desejar, sem medo de que um deles seja percebido como o valor do parâmetro case_sensitive.

É possível e assim.

 def func(first, second, *, kwonly): 


Examinaremos mais de perto como simplesmente * difere de * args.

 def func(first, second, *, kwonly=True): print(first, second, kwonly) def func2(first, second, *args, kwonly=True): print(first, second, *args, kwonly) func(1) #-> TypeError: func() missing 1 required positional argument: 'second' func(1, 2) #-> 1 2 True func(1, 2, False) #-> TypeError: func() takes 2 positional arguments but 3 were given #  *    ,  #        #   func(1, 2, kwonly=False) #-> 1 2 False func2(1, 2, False) #-> 1 2 False True # *args      # ,       #    (>2)  #  


Um recurso interessante está associado aos parâmetros padrão: eles são calculados no estágio de compilação do módulo no bytecode; portanto, é melhor não usar tipos mutáveis ​​lá. Declaramos uma função que adiciona um elemento ao final da lista; se o segundo argumento for omitido, a função retornará uma nova lista contendo apenas esse elemento.

 def add_to(elem, collection=[]): collection.append(elem) return collection a = ["a", "c"] print(add_to("b", a)) # -> ['a', 'c', 'b'] print(add_to("a")) # -> ['a'] print(add_to("b")) # -> ['a', 'b']   'a'? 

Os valores padrão são armazenados no campo __defaults__, você pode descobrir o que existe a qualquer momento.

 print(add_to.__defaults__) # -> (['a', 'b'],) 

Como o argumento padrão (uma lista vazia) foi criado no momento em que o programa foi iniciado e não foi recriado novamente, obtivemos exatamente esse comportamento.

Você pode corrigir esse comportamento se tornar o valor padrão um tipo imutável e criar uma lista no corpo da função:

 def add_to(elem, collection=None): collection = collection or [] collection.append(elem) return collection 

Preste atenção ao comando

 collection = collection or [] 

este é um analógico mais curto (e menos claro, embora não seja para todos)

 collection = collection if collection else [] 


Link para a próxima parte

Source: https://habr.com/ru/post/pt421993/


All Articles