Maison > développement back-end > Tutoriel Python > Typage progressif de Python : améliorer de manière flexible la sécurité et les performances du code

Typage progressif de Python : améliorer de manière flexible la sécurité et les performances du code

Barbara Streisand
Libérer: 2024-11-27 18:29:15
original
383 Les gens l'ont consulté

Python

La saisie progressive en Python change la donne pour les développeurs comme nous qui veulent le meilleur des deux mondes : flexibilité dynamique et sécurité statique. Il ne s’agit pas de choisir son camp ; il s'agit de trouver le juste milieu qui convient à nos projets.

Commençons par les bases. Python a toujours été typé dynamiquement, ce qui signifie que nous n'avons pas besoin de déclarer de types de variables. Cela nous donne une flexibilité incroyable, mais cela peut également conduire à des erreurs d’exécution difficiles à détecter. C'est là qu'intervient la saisie progressive.

Avec la saisie progressive, nous pouvons ajouter des indices de saisie à notre code. Ces astuces sont facultatives, nous pouvons donc les introduire progressivement (d'où le nom) sans casser le code existant. Voici un exemple simple :

def greet(name: str) -> str:
    return f"Hello, {name}!"

print(greet("Alice"))  # Output: Hello, Alice!
print(greet(42))  # This will run, but a type checker would warn us
Copier après la connexion
Copier après la connexion

Dans cet exemple, nous disons à Python que le nom doit être une chaîne et que la fonction doit renvoyer une chaîne. Mais Python n'appliquera pas cela au moment de l'exécution – c'est à nous d'utiliser un vérificateur de type comme mypy pour détecter les problèmes potentiels.

Maintenant, approfondissons un peu. L’un des avantages de la saisie progressive est que nous pouvons mélanger du code tapé et non typé. Ceci est très utile lorsque nous travaillons avec des bases de code héritées ou des bibliothèques tierces qui n'utilisent pas d'indices de type.

def process_data(data: list[int]) -> int:
    return sum(data)

# This function doesn't use type hints
def get_data():
    return [1, 2, 3, 4, 5]

result = process_data(get_data())  # This works fine
Copier après la connexion

Ici, process_data utilise des indices de type, mais pas get_data. Ils peuvent toujours travailler ensemble de manière transparente.

Mais la saisie progressive ne consiste pas seulement à ajouter : int ici et là. Cela ouvre un tout nouveau monde de possibilités. Par exemple, nous pouvons créer des types personnalisés pour rendre notre code plus expressif :

from typing import NewType

UserId = NewType('UserId', int)

def get_user_info(user_id: UserId) -> dict:
    # Fetch user info from database
    pass

user_id = UserId(12345)
info = get_user_info(user_id)  # This is fine
info = get_user_info(12345)  # A type checker would warn about this
Copier après la connexion

Cela nous aide à détecter les erreurs logiques. Bien sûr, un identifiant utilisateur peut être un nombre entier, mais tous les entiers ne constituent pas un identifiant utilisateur valide.

Parlons maintenant de quelques concepts plus avancés. La covariance et la contravariance sont des termes sophistiqués qui décrivent comment nous pouvons utiliser les sous-types et les supertypes dans nos astuces de type. C'est un peu hallucinant au début, mais c'est super utile.

from typing import List, Callable

class Animal:
    def make_sound(self):
        pass

class Dog(Animal):
    def make_sound(self):
        return "Woof!"

def animal_sounds(animals: List[Animal]) -> List[str]:
    return [animal.make_sound() for animal in animals]

dogs: List[Dog] = [Dog(), Dog()]
sounds = animal_sounds(dogs)  # This is fine because Dog is a subtype of Animal
Copier après la connexion

Dans cet exemple, nous utilisons la covariance. Nous pouvons transmettre une liste de chiens à une fonction attendant une liste d'animaux car Dog est un sous-type d'animal.

La contravariance est le contraire. C'est utile lorsque nous avons affaire à des arguments de fonction :

def feed_animal(animal: Animal):
    print("Feeding animal")

def feed_dog(dog: Dog):
    print("Feeding dog")

def do_feeding(feeder: Callable[[Animal], None], animal: Animal):
    feeder(animal)

do_feeding(feed_animal, Dog())  # This is fine
do_feeding(feed_dog, Animal())  # A type checker would warn about this
Copier après la connexion

Ici, nous pouvons passer feed_animal à do_feeding car il peut gérer n'importe quel animal, y compris les chiens. Mais nous ne pouvons pas dépasser feed_dog car il pourrait ne pas être capable de gérer tous les types d'animaux.

Ces concepts peuvent sembler un peu abstraits, mais ils sont incroyablement puissants lorsque nous concevons des systèmes complexes.

Parlons maintenant de la façon dont nous pouvons progressivement introduire le typage statique dans une grande base de code Python. Ce n'est pas une proposition du tout ou rien. Nous pouvons commencer petit et progresser progressivement.

Tout d’abord, nous souhaiterions peut-être ajouter des indices de type à nos API publiques. Cela aide les utilisateurs de notre code à comprendre quels types ils doivent transmettre et ce qu'ils obtiendront. Ensuite, nous pouvons passer aux sections critiques de notre code – des zones où les bogues liés au type seraient particulièrement problématiques.

Au fur et à mesure que nous ajoutons d'autres indices de type, nous commencerons à voir des avantages. Les vérificateurs de type peuvent détecter les bogues potentiels avant même que nous exécutions notre code. Nos IDE peuvent fournir une meilleure prise en charge de la saisie semi-automatique et de la refactorisation. Et notre code devient auto-documenté dans une certaine mesure.

Mais il y a un équilibre à trouver. Nous ne voulons pas exagérer avec les astuces de type et perdre la lisibilité et la simplicité qui font la grandeur de Python. Parfois, il est acceptable de laisser des éléments non typés, en particulier pour un code simple et évident.

Regardons un exemple de saisie progressive d'une fonction :

def greet(name: str) -> str:
    return f"Hello, {name}!"

print(greet("Alice"))  # Output: Hello, Alice!
print(greet(42))  # This will run, but a type checker would warn us
Copier après la connexion
Copier après la connexion

Nous avons commencé sans aucune indication de type, puis nous en avons ajouté quelques-unes de base et enfin créé des types personnalisés pour une version entièrement typée. Chaque étape améliore la robustesse de notre code sans modifier ses fonctionnalités.

L'un des aspects les plus intéressants de la saisie progressive est qu'elle peut entraîner des améliorations de performances. Lorsque nous fournissons des informations de type, Python peut parfois optimiser notre code. Par exemple, il pourrait être capable d'utiliser des structures de données plus efficaces ou d'éviter des vérifications de type inutiles.

Mais le plus grand avantage de la saisie progressive est peut-être la façon dont elle change la façon dont nous pensons à notre code. Lorsque nous commençons à considérer les types, nous découvrons souvent des incohérences logiques ou des cas extrêmes potentiels auxquels nous n'avions pas pensé auparavant. C'est comme avoir une conversation avec notre futur moi sur ce que notre code est censé faire.

Bien sûr, la saisie progressive n'est pas sans défis. Cela peut rendre notre code plus verbeux, et il existe une courbe d'apprentissage pour utiliser efficacement les astuces de type. Nous devons également faire attention à ne pas tomber dans le piège qui consiste à penser que les indices de type garantissent l'exactitude : ils sont un outil pour nous aider à détecter certains types d'erreurs, mais ils ne sont pas une solution miracle.

Pour conclure, examinons quelques bonnes pratiques pour utiliser la saisie progressive en Python :

  1. Commencez par les parties critiques de votre base de code. Concentrez-vous sur les domaines où les bogues liés au type seraient les plus problématiques.

  2. Utilisez régulièrement des vérificateurs de type comme mypy. Ils constituent votre première ligne de défense contre les problèmes liés à la typographie.

  3. Ne vous sentez pas obligé de tout taper. Parfois, la saisie dynamique est exactement ce dont vous avez besoin.

  4. Utilisez des outils comme MonkeyType pour générer automatiquement des astuces de type pour le code existant.

  5. N'oubliez pas que les indices de type sont autant destinés aux humains qu'aux machines. C'est une forme de documentation.

  6. Restez à jour avec les fonctionnalités de saisie de Python. Ils évoluent et s'améliorent constamment.

La saisie progressive en Python est un outil puissant qui nous permet d'exploiter les avantages de la saisie statique et dynamique. Il ne s'agit pas de restreindre ce que nous pouvons faire avec Python, mais de nous donner plus d'options et plus d'outils pour écrire du code robuste et maintenable. Comme pour tout outil, la clé est d’apprendre quand et comment l’utiliser efficacement. Alors allez-y et tapez – progressivement !


Nos créations

N'oubliez pas de consulter nos créations :

Centre des investisseurs | Vie intelligente | Époques & Échos | Mystères déroutants | Hindutva | Développeur Élite | Écoles JS


Nous sommes sur Medium

Tech Koala Insights | Epoques & Echos Monde | Support Central des Investisseurs | Mystères déroutants Medium | Sciences & Epoques Medium | Hindutva moderne

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!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal