[Astuces Python] 5 astuces Python mineures mais utiles

Je voudrais vous présenter une technique de codage Python que je n'ai pas beaucoup vue. Je suis désolé si c'était inopinément majeur. Je voudrais inclure autant d'exemples de code que possible pour montrer comment cela fonctionne réellement. Puisqu'il résume les technologies de niche, on suppose que vous pouvez écrire Python dans une certaine mesure.

functools.partial Vous pouvez l'utiliser pour ** créer une fonction avec des arguments fixes ** pour une fonction. Je pense que c'est plus rapide de regarder le code.

import functools

def add(x, y):
    return x + y

add_fixed_y = functools.partial(add, y=5)
print(add_fixed_y(2)) # 7

Je ne sais pas à quoi cela servira à lui seul, je voudrais donc présenter ma propre utilisation. Je l'utilise pour la fonction ** ʻopen` ** du fichier.

open_utf_8 = functools.partial(open, encoding="utf-8")
r_open_utf_8 = functools.partial(open_utf_8, mode="r")
w_open_utf_8 = functools.partial(open_utf_8, mode="w")

with w_open_utf_8("something_great.txt") as wf:
    wf.write("Hello World!")

En faisant cela, vous pouvez réduire le nombre de constantes à partir du code et empêcher de taper dans la partie ʻencoding`.

suivant et générateur

Les expressions à l'intérieur de la notation d'inclusion de liste peuvent être utilisées pour les expressions génératrices, et la création d'objets générateurs a été introduite dans d'autres articles.

gen = (i ** 2 for i in range(10))
print(gen) # <generator object <genexpr> at 0x~~>

En quoi est-ce utile dans le codage réel? Je l'utilise pour trouver le premier index ** qui répond aux critères **. Il est utilisé pour ** arrondir la chaîne de caractères au nombre d'octets spécifié ou moins **.

from itertools import accumulate

def str_clamp_bytes(value: str, max_bytes: int) -> str:
    byte_count = (len(s.encode("utf-8")) for s in value)
    try:
        end_slice = next(i for i, v in enumerate(accumulate(byte_count)) if v > max_bytes)
    except StopIteration:
        return value
    return value[:end_slice]

(i for i, v in enumerate (accumulate (byte_count)) if v> max_bytes) est le générateur et ʻif v> max_bytes est l'expression conditionnelle. ʻEnd_slice reçoit le premier index qui satisfait v> max_bytes. S'il n'y a pas d'index qui remplit les conditions, une exception StopIteration se produira, alors attrapez-la et retournez la chaîne de caractères d'origine. Le générateur est suffisant car byte_count n'est utilisé que pour ʻaccumulate`.

Variable globale __debug__

Cette variable devient «False» lorsque l'option «-O» (pas zéro) est ajoutée au démarrage. Si vous ajoutez l'option -O, l'instruction ʻassert` devient invalide et vous pouvez accélérer le programme, ainsi vous pouvez l'ajouter dans la version du produit sans aucun problème. Je l'utilise pour le processus de ** livraison uniquement de la version du produit **.

def broadcast_debug():
    pass

def broadcast_prod():
    pass

(broadcast_debug if __debug__ else broadcast_prod)()

Décorateur lru_cache

En mémorisant la paire argument de fonction / valeur de retour dans le dictionnaire, l'argument précédemment passé renverra la valeur de retour précédente sans traitement.

from functools import lru_cache

@lru_cache
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(10))

Puisqu'il s'agit d'un dictionnaire, la vitesse d'accès est inférieure à l'écriture pure de mémo, mais la facilité d'utilisation est excellente. Après cela, il peut être géré même si ** chaînes de caractères, etc. sont utilisées comme arguments **, ce qui ne peut pas être géré par la conversion de mémo.

inspect.getmembers Vous pouvez ** obtenir tous les membres du module **. Vous pouvez spécifier le type de membre avec le deuxième argument.

import inspect
import copy

print(inspect.getmembers(copy, inspect.isclass))
# >> [('Error', <class 'copy.Error'>), ('error', <class 'copy.Error'>)]

** Vous pouvez extraire toutes les classes du module **, ainsi vous pouvez les obtenir toutes en même temps sans les tracas de shared_classes = [class_A, class_B, ...]. Et vous n'avez pas à vous soucier d'oublier de l'ajouter. L'objet de classe a un membre __bases__, et tous les objets de classe hérités sont inclus en tant que tapples, donc je pense que vous pouvez utiliser cette zone pour filtrer.

finalement

J'ai introduit une astuce que je trouve "pratique mais je ne vois pas grand chose". Veuillez me faire savoir si vous avez des erreurs ou des fautes de frappe.

Recommended Posts

[Astuces Python] 5 astuces Python mineures mais utiles
[Python] Débogage super utile
3 astuces du notebook Jupyter (Python)
liens de mémo utiles python
Python est douloureux. Mais utilisez
Astuces utiles liées à la liste et aux instructions en Python
Installez Python 3.7 Anaconda sur MAC, mais Python 2
Python mais visualisation facile avec PixieDust