Cet article présente et explique principalement comment écrire du code Python efficace et élégant. Les amis qui en ont besoin peuvent s'y référer
Une partie de cet article est extraite du livre : "Effective Python" & "Python3 Cookbook". ", mais des modifications ont également été apportées et la propre compréhension et application des meilleures pratiques par l'auteur a été ajoutée.
Le texte intégral compte environ 9956 mots et sa lecture peut prendre 24 minutes.
Coupe de liste Pythonic
list[start:end:step]
Si vous commencez à couper depuis le début de la liste, ignorez le 0 dans le bit de départ, tel comme list[:4]
Si vous coupez jusqu'à la fin de la liste, ignorez le 0 dans le bit de fin. Par exemple, list[3:]
Lorsque vous coupez la liste, il y aura. ne posera aucun problème même si l'index de début ou de fin franchit la limite
Le découpage de liste ne modifie pas la liste d'origine. Lorsque les index sont tous laissés vides, une copie de la liste originale sera générée
Compréhensions de liste
Utilisez les compréhensions de liste pour remplacer map
et filter
N'utilisez pas de compréhensions de listes contenant plus de deux expressions
Lorsqu'il y a beaucoup de données, Les compréhensions de liste peuvent Cela consomme beaucoup de mémoire. À l'heure actuelle, il est recommandé d'utiliser l'expression génératrice
itération
lorsque vous avez besoin d'obtenir le. index, utilisez enumerate
enumerate
Vous pouvez accepter le deuxième paramètre comme valeur ajoutée à index
lors de l'itération
Utilisez zip
pour parcourir deux itérateurs en même temps
zip
Renvoie un tuple lors du parcours
À propos de for
et while
else
blocs après la boucle
La boucle appellera le code dans après qu'il se termine normalementelse
Si vous utilisez break
pour casser hors de la boucle, else
ne sera pas exécuté Lorsque la séquence à parcourir est vide, exécutez immédiatement else
Itération inverse.
Pour les séquences ordinaires (listes), nous pouvons passer la fonction intégrée La fonction reversed()
effectue une itération inverse :
De plus, vous pouvez également effectuez une itération inverse sur la classe en implémentant la méthode __reversed__
dans la classe :
try/except/else/finally
Si aucune exception ne se produit dans try
, le code dans else
sera appelé
else
dans finally
Avant d'exécuter
finira par exécuter finally
, où vous pourrez nettoyer la fonction
utilise un décorateur
Le décorateur permet de modifier le code de la fonction d'origine sans le changer Modifier une fonction existante. Un scénario courant consiste à ajouter une phrase de débogage ou à ajouter une log
surveillance
à une fonction existante. Par exemple :
De plus, vous pouvez. écrivez aussi Le décorateur qui reçoit les paramètres est en fait une fonction imbriquée dans la couche externe du décorateur d'origine :
Mais il y a un problème lors de l'utilisation du décorateur comme ci-dessus :
Autrement dit, la fonction d'origine a été remplacée par la fonction new_fun
dans le décorateur. Appeler une fonction décorée équivaut à appeler une nouvelle fonction. Lors de l'affichage des paramètres, des commentaires et même des noms de fonction de la fonction d'origine, vous ne pouvez voir que les informations relatives au décorateur. Afin de résoudre ce problème, nous pouvons utiliser la méthode
propre functools.wraps
de Python.
functools.wraps
est une méthode très hack. Elle peut être utilisée comme décorateur sur la fonction qui sera renvoyée à l'intérieur du décorateur. En d'autres termes, il s'agit d'un décorateur de décorateurs, et prend la fonction originale comme paramètre. Sa fonction est de conserver diverses informations de la fonction originale, de sorte que lorsque nous visualisons ultérieurement les informations de la fonction originale décorée, elles puissent rester exactement. identique à la fonction d'origine.
De plus, notre décorateur peut parfois faire plus d'une chose, auquel cas l'événement doit être séparé en tant que fonction supplémentaire. Mais comme elle ne peut concerner que le décorateur, une classe de décorateur peut être construite à ce stade. Le principe est très simple, l'essentiel est d'écrire la méthode __call__
dans la classe pour que la classe puisse être appelée comme une fonction.
Utiliser des générateurs
Envisagez d'utiliser des générateurs pour réécrire des fonctions qui renvoient directement des listes
Il y a plusieurs petits problèmes avec cette méthode :
Chaque fois qu'un résultat répondant aux conditions est obtenu, la méthode append
doit être appelée. Mais en fait, nous ne nous concentrons pas du tout sur cette méthode, c'est juste un moyen pour nous d'atteindre notre objectif. En fait, nous avons seulement besoin de index
Le result
retourné peut continuer à être optimisé.
Les données sont stockées dans result
Si la quantité de données est importante, elles occuperont plus de mémoire
Par conséquent, il est préférable d'utiliser le générateur generator
. Un générateur est une fonction qui utilise une expression yield
Lorsque le générateur est appelé, il ne s'exécutera pas réellement, mais renverra un itérateur à chaque fois que la fonction next
intégrée est appelée sur l'itérateur. Le générateur passe à l'expression yield
suivante :
Après avoir obtenu un générateur, vous pouvez le parcourir normalement :
Si vous avez encore besoin d'une liste, vous pouvez utiliser le résultat de l'appel de fonction comme paramètre puis appeler la list
méthode
Objet itérable
Il convient de noter que les itérateurs ordinaires ne peuvent itérer que pendant un tour et que les appels répétés après un tour ne sont pas valides. La façon de résoudre ce problème est que vous pouvez définir une classe de conteneur itérable : Pas de problème :
Mais il faut noter qu'il ne s'agit que d'un itérateur qui implémente la méthode
et ne peut être itéré que dans la boucle; si vous souhaitez passer Pour l'itération de la méthode, vous devez utiliser la méthode
:__iter__
for
next
iter
Utiliser des paramètres de position
Parfois, le nombre de paramètres reçus par la méthode peut ne pas être certain, comme par exemple Définir une méthode de sommation qui doit recevoir au moins deux paramètres :
Pour ce genre de fonction qui n'a pas forcément un certain nombre de paramètres et ne se soucie pas de l'ordre dans lequel les paramètres sont passés, il faut utiliser les paramètres positionnels
:*args
Cependant, il convient de noter que le paramètre de longueur variable
lorsqu'il est transmis à la fonction. Cela signifie que si vous passez un générateur en paramètre à une fonction, le générateur sera parcouru en premier et converti en tuple. Cela peut consommer beaucoup de mémoire :
args
tuple
Utiliser des arguments de mots-clés
Les arguments de mots-clés améliorent la lisibilité du code
Peut transmettre les paramètres de mots-clés fournir des valeurs par défaut pour les fonctions pour faciliter l'expansion des paramètres de fonctionDéfinir des fonctions qui ne peuvent utiliser que des paramètres de mots-clés
De la manière ordinaire , lors de l'appel, il ne forcera pas l'utilisation des paramètres de mots-clés lorsque
Utilisez la méthode de forçage des paramètres de mots-clés dans
Python3Utilisez la méthode de forçage des paramètres de mots clés dans
Python2À propos des valeurs par défaut des paramètres
C'est un cliché :La valeur par défaut d'une fonction ne sera définie qu'une seule fois lorsque le programme chargera le module et lit la définition de la fonction
En d'autres termes, si une valeur dynamique est affecté à un paramètre (Par exemple ou
), si d'autres paramètres sont affectés aux paramètres lors de l'appel ultérieur de la fonction, lorsque cette fonction sera à nouveau appelée dans le futur, le défini précédemment la valeur par défaut changera et deviendra la valeur attribuée lors du dernier appel Valeur :.
Par conséquent, il est plus recommandé d'utiliser None
comme paramètre par défaut, et d'attribuer la valeur après jugement dans la fonction :
Class__slots__
Par défaut, Python utilise un dictionnaire pour enregistrer les attributs d'instance d'un objet. Cela nous permet d'ajouter dynamiquement de nouveaux attributs aux instances de classe au moment de l'exécution :
Cependant, ce dictionnaire gaspille de l'espace supplémentaire - souvent, nous ne le créerons pas avec autant d'attributs. Ainsi avec __slots__
vous pouvez dire à Python
de ne pas utiliser de dictionnaire mais une collection fixe pour allouer de l'espace.
__call__
En définissant la méthode __call__
dans une classe, les instances de la classe peuvent être appelées comme des fonctions ordinaires.
L'avantage d'implémenter cette méthode est que l'état peut être enregistré via les propriétés de la classe sans avoir à créer une fermeture ou une variable globale.
@classmethod
& @staticmethod
@classmethod
est très similaire à @staticmethod
, mais leurs scénarios d'utilisation sont différents.
Les méthodes ordinaires de la classe utilisent toutes self
comme premier paramètre, ce qui signifie que lorsqu'elles sont appelées via une instance, la portée de l'instance est transmise à la méthode
@classmethod
; Utiliser cls
comme premier paramètre signifie passer dans la portée de la classe elle-même. Qu'il soit appelé via une classe ou une instance de classe, le premier paramètre transmis par défaut sera la classe elle-même
@staticmethod
Il n'est pas nécessaire de transmettre des paramètres par défaut, semblable à une fonction ordinaire
Apprenons leurs scénarios d'utilisation à travers des exemples :
Supposons que nous devions créer une classe nommée Date
pour stocker trois données année/mois/jour
Le code ci-dessus crée la classe Date
, qui définit l'attribut day/month/year
lors de l'initialisation, et définit un property
à getter
, qui peut être instancié via time
Obtenir l'heure stockée :
Mais que se passe-t-il si nous voulons changer la façon dont les propriétés sont transmises ? Après tout, c'est embêtant de devoir passer les trois attributs année/mois/jour lors de l'initialisation. Pouvez-vous trouver un moyen de créer une instance de 2016-11-09
en passant une chaîne comme Date
sans modifier l'interface et les méthodes existantes ?
Vous pourriez penser à une méthode comme celle-ci :
Mais ce n'est pas suffisant :
Écrivez une méthode supplémentaire en dehors de la classe, each Cette fois, vous devez formater puis récupérer les paramètres
Cette méthode est uniquement liée à la Date
classe
ne résout pas le problème du trop grand nombre de paramètres passés dans
Vous pouvez l'utiliser à ce moment @classmethod
, créer une nouvelle chaîne de format à l'intérieur de la classe et renvoyer la méthode de l'instance de classe :
De cette façon, nous peut l'appeler via la classe Date
La méthode from_string
crée une instance et n'envahit ni ne modifie l'ancienne méthode d'instanciation :
Avantages :
Dans @classmethod
, vous pouvez transmettre cls
Paramètres, obtenez la même commodité que lors de l'appel de classes en externe
Vous pouvez y encapsuler davantage la méthode pour améliorer la réutilisabilité
Plus conforme à programmation orientée objet
Et @staticmethod
, parce qu'elle est similaire à une fonction ordinaire, vous pouvez mettre la méthode d'assistance
liée à cette classe comme @staticmethod
dans la classe, puis appelez cette méthode directement via la classe.
Après avoir placé les fonctions de classe auxiliaires liées à la date en tant que méthodes @staticmethod
au sein de la classe Date
, ces méthodes peuvent être appelées via la classe :
Créer un gestionnaire de contexte
Gestionnaire de contexte, l'introduction populaire est la suivante : avant l'exécution du bloc de code, le travail de préparation est effectué en premier après l'exécution du bloc de code, la finition ; le travail est terminé. Travail de traitement. L'instruction with
apparaît souvent avec le gestionnaire de contexte. Les scénarios classiques incluent :
Grâce à l'instruction with
, le code termine l'opération d'ouverture du fichier et ferme automatiquement le fichier lorsque l'appel se termine ou qu'une exception se produit pendant la lecture, c'est-à-dire le traitement après la lecture et l'écriture du fichier est terminée. Si vous ne passez pas le gestionnaire de contexte, le code sera comme ceci :
Ce n'est pas plus encombrant ? Ainsi, l'avantage d'utiliser le gestionnaire de contexte est qu'il nous aide automatiquement à gérer le travail lorsque le bloc de code démarre et termine son exécution en appelant nos rappels prédéfinis. Grâce aux méthodes __enter__
et __exit__
de la classe personnalisée, nous pouvons personnaliser un gestionnaire de contexte.
peut alors être appelé comme ceci :
Lors de l'appel :
Le with
L'instruction stocke d'abord temporairement la méthode ReadFile
__exit__
, puis appelle la méthode ReadFile
__enter__
de la classe
__enter__
with
pour ouvrir le fichier et stocke le résultat Renvoyé à l'instruction
file_read
le résultat de l'étape précédente est passé au paramètre
with
opère sur le paramètre file_read
au sein du
with
Une fois la lecture terminée, l'instruction __exit__
appelle la méthode
__exit__
__exit__
Il convient de noter que dans la méthode True
Inside, nous fermons le fichier, mais renvoyons with
à la fin, donc l'erreur ne sera pas générée par l'instruction with
. Sinon, l'instruction
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!