Sélection du bon outil pour le travail – Real Python

By | septembre 11, 2019

Python pas cher

Êtes-vous un développeur C ++ comparant Python à C ++? Vous regardez Python et vous vous demandez pourquoi? Vous vous demandez comment Python se compare aux concepts que vous connaissez déjà? Ou peut-être avez-vous un pari sur qui gagnerait si vous bloquiez C ++ et Python dans une cage et les laissiez se battre? Alors cet article est pour vous!

Dans cet article, vous en apprendrez plus sur:

  • Différences et similitudes lorsque vous comparez Python et C ++
  • Python peut être un meilleur choix pour un problème et vice versa
  • Ressources à consulter lorsque vous avez des questions lors de l'apprentissage de Python

Cet article s’adresse aux développeurs C ++ qui apprennent Python. Il suppose une connaissance de base des deux langages et utilisera les concepts de Python 3.6 et versions ultérieures, ainsi que de C ++ 11 ou ultérieur.

Penchons-nous maintenant sur Python vs C ++!

Comparaison des langues: Python vs C ++

Vous trouverez fréquemment des articles qui vantent les vertus d’un langage de programmation par rapport à un autre. Très souvent, ils s’efforcent de promouvoir une langue en dégradant l’autre. Ce n'est pas ce type d'article.

Lorsque vous comparez Python à C ++, rappelez-vous qu’il s’agit des deux outils et qu’ils ont tous deux des utilisations différentes. Pensez à comparer un marteau et un tournevis. Vous pourrait utilisez un tournevis pour enfoncer les clous, et vous pourrait Utilisez un marteau pour forcer les vis, mais aucune expérience ne sera aussi efficace.

Utiliser le bon outil pour le travail est important. Dans cet article, vous découvrirez les fonctionnalités de Python et de C ++ qui font de chacune d’elles le bon choix pour certains types de problèmes. Donc, ne considérez pas le «vs» dans Python vs C ++ comme signifiant «contre». Considérez-le plutôt comme une comparaison.

Compilation vs machine virtuelle

Commençons par la plus grande différence lorsque vous comparez Python et C ++. En C ++, vous utilisez un compilateur qui convertit votre code source en code machine et génère un exécutable. L'exécutable est un fichier séparé qui peut ensuite être exécuté en tant que programme autonome:

Compiler un programme C ++ pour Windows.

Ce processus génère les instructions réelles de la machine pour le processeur et le système d’exploitation spécifiques pour lesquels il est conçu. Dans ce dessin, il s’agit d’un programme Windows. Cela signifie que vous devez recompiler votre programme séparément pour Windows, Mac et Linux:

Compiler un programme C ++ sur trois systèmes d'exploitation.

Vous devrez probablement modifier votre code C ++ pour s’exécuter également sur ces différents systèmes.

Python, en revanche, utilise un processus différent. Maintenant, rappelez-vous que vous allez regarder CPython qui est l'implémentation standard pour le langage. Sauf si vous faites quelque chose de spécial, c'est le Python que vous utilisez.

Python s'exécute chaque fois que vous exécutez votre programme. Il compile votre source comme le compilateur C ++. La différence est que Python se compile en bytecode au lieu du code machine natif. Bytecode est le code d'instruction natif de la machine virtuelle Python. Pour accélérer les exécutions ultérieures de votre programme, Python stocke le bytecode dans .pyc des dossiers:

Python compile un fichier py en un fichier pyc.

Si vous utilisez Python 2, vous trouverez ces fichiers à côté du fichier .py des dossiers. Pour Python 3, vous les trouverez dans un __pycache__ annuaire.

Le bytecode généré ne s’exécute pas nativement sur votre processeur. Au lieu de cela, il est exécuté par la machine virtuelle Python. Ceci est similaire à la machine virtuelle Java ou à .NET Common Runtime Environment. La première exécution de votre code entraînera une étape de compilation. Ensuite, le bytecode sera interprété pour s'exécuter sur votre matériel spécifique:

Python compile un fichier py en un fichier pyc puis l'exécute.

Tant que le programme n’a pas été modifié, chaque exécution ultérieure ignorera l’étape de la compilation et utilisera le bytecode précédemment compilé pour interpréter:

Python exécute un fichier pyc.

L'interprétation du code sera plus lente que l'exécution du code natif directement sur le matériel. Alors pourquoi Python fonctionne-t-il de cette façon? En interprétant le code dans une machine virtuelle, seule la machine virtuelle doit être compilée pour un système d'exploitation spécifique sur un processeur spécifique. Tout le code Python qu'il exécute sera exécuté sur tout ordinateur doté de Python.

Une autre caractéristique de ce support multiplate-forme réside dans le fait que la bibliothèque standard étendue de Python est écrite pour fonctionner sur tous les systèmes d'exploitation.

En utilisant pathlibpar exemple, gérera les séparateurs de chemin pour vous que vous soyez sous Windows, Mac ou Linux. Les développeurs de ces bibliothèques ont passé beaucoup de temps à le rendre portable, vous n’avez donc pas à vous en soucier dans votre programme Python!

Avant de poursuivre, commençons par garder trace du tableau de comparaison Python vs C ++. Lorsque vous couvrez de nouvelles comparaisons, elles seront ajoutées en italique:

Fonctionnalité Python C ++
Exécution plus rapide X
Exécution multiplateforme X

Maintenant que vous avez constaté les différences de temps d’exécution lorsque vous comparez Python à C ++, étudions maintenant les spécificités de la syntaxe des langages.

Différences de syntaxe

Python et C ++ partagent de nombreuses similitudes syntaxiques, mais quelques domaines méritent d’être abordés:

  • Espace blanc
  • Expressions booléennes
  • Variables et pointeurs
  • Des compréhensions

Commençons par le plus controversé: les espaces.

Espace blanc

La première chose que la plupart des développeurs remarquent en comparant Python et C ++ est le «problème des espaces». Python utilise les principaux espaces pour marquer la portée. Cela signifie que le corps d'un si bloc ou autre structure similaire est indiquée par le niveau d'indentation. C ++ utilise des accolades () pour indiquer la même idée.

Bien que le lexer Python accepte tous les espaces tant que vous êtes cohérent, PEP8 (le guide de style officiel de Python) spécifie 4 espaces pour chaque niveau d’indentation. La plupart des éditeurs peuvent être configurés pour le faire automatiquement.

Il ya déjà eu énormément d’écrit, de cris et de discours sur les règles d’espace de Python, alors sautons le problème et passons à autre chose.

Au lieu de compter sur un marqueur lexical comme ; pour terminer chaque instruction, Python utilise la fin de la ligne. Si vous avez besoin d'étendre une instruction sur une seule ligne, vous pouvez utiliser la barre oblique inverse () pour indiquer que. (Notez que si vous êtes entre parenthèses, le caractère de continuation n’est pas nécessaire.)

Il y a des gens qui sont mécontents des deux côtés de la question des espaces blancs. Certains développeurs Python adorent ne pas avoir à taper d'accolades et de points-virgules. Certains développeurs C ++ détestent compter sur le formatage. Apprendre à être à l'aise avec les deux est votre meilleur pari.

Maintenant que vous avez examiné la question des espaces, passons à une question un peu moins controversée: les expressions booléennes.

Expressions booléennes

La façon dont vous utiliserez les expressions booléennes changera légèrement entre Python et C ++. En C ++, vous pouvez utiliser des valeurs numériques pour indiquer vrai ou faux, en plus des valeurs intégrées. Tout ce qui est évalué à 0 est considéré faux, alors que toute autre valeur numérique est vrai.

Python a un concept similaire mais l’étend à d’autres cas. Les bases sont assez similaires. La documentation Python indique que les éléments suivants sont évalués comme suit: Faux:

  • Constantes définies comme fausses:
  • Zéros de tout type numérique:
    • 0
    • 0.0
    • 0j
    • Décimal (0)
    • Fraction (0, 1)
  • Séquences et collections vides:
    • ''
    • ()
    • []
    • ensemble()
    • gamme (0)

Tous les autres articles sont Vrai. Cela signifie qu'une liste vide [] est Faux, alors qu'une liste ne contenant que zéro [0] est encore Vrai.

La plupart des objets seront évalués à Vrai, sauf si l'objet a __bole __ () qui retourne Faux ou __len __ () qui renvoie 0. Cela vous permet d'étendre vos classes personnalisées pour qu'elles agissent comme des expressions booléennes.

Python a également quelques légères modifications par rapport au C ++ dans les opérateurs booléens. Pour commencer, si et tandis que les instructions ne nécessitent pas les parenthèses qui les entourent comme elles le font en C ++. Les parenthèses peuvent aider à la lisibilité, cependant, alors utilisez votre meilleur jugement.

La plupart des opérateurs booléens C ++ ont des opérateurs similaires en Python:

Opérateur C ++ Opérateur Python
&& et
|| ou
! ne pas
Et Et
| |

La plupart des opérateurs sont similaires à C ++, mais si vous souhaitez vous rafraîchir, vous pouvez lire Opérateurs et Expressions en Python.

Variables et pointeurs

Lorsque vous commencez à utiliser Python après avoir écrit en C ++, il est possible que vous ne pensiez pas beaucoup aux variables. Ils semblent généralement fonctionner comme en C ++. Cependant, ils ne sont pas les mêmes. Tandis qu'en C ++, vous utilisez des variables pour référencer des valeurs, en Python, vous utilisez des noms.

Tout d’abord, revenons un peu en arrière et examinons plus en détail le modèle objet de Python.

En python, tout est un objet. Les nombres sont contenus dans des objets. Les modules sont contenus dans des objets. À la fois l'objet d'une classe et la classe elle-même sont des objets. Les fonctions sont aussi des objets:

>>>

>>> a_list_object = liste()
>>> a_list_object
[]
>>> a_class_object = liste
>>> a_class_object

>>> def dis salut(prénom):
...      impression(F'Bonjour, prénom')
...
>>> a_function_object = dis salut
>>> a_function_object

Appel liste() crée un nouvel objet de liste, que vous affectez à a_list_object. Utiliser le nom de la classe liste à lui seul, place une étiquette sur l'objet de classe. Vous pouvez également placer une nouvelle étiquette sur une fonction. C'est un outil puissant et, comme tous les outils puissants, il peut être dangereux. (Je vous regarde, M. Chainsaw.)

Pour revenir à la discussion entre Python et C ++, notez que ce comportement est différent de ce que vous verrez en C ++. Contrairement à Python, C ++ a des variables assignées à un emplacement de mémoire, et vous devez indiquer la quantité de mémoire que cette variable utilisera:

int an_int;
flotte a_big_array_of_floats[[[[REALLY_BIG_NUMBER];

En Python, tous les objets sont créés en mémoire et vous leur appliquez des étiquettes. Les étiquettes elles-mêmes n’ont pas de types et peuvent être placées sur n’importe quel type d’objet:

>>>

>>> mon_nom_flexible = 1
>>> mon_nom_flexible
1
>>> mon_nom_flexible = 'Ceci est une chaîne'
>>> mon_nom_flexible
'Ceci est une chaîne'
>>> mon_nom_flexible = [[[[3, 'Plus d'informations', 3.26]
>>> mon_nom_flexible
[3, 'more info', 3.26]
>>> mon_nom_flexible = impression
>>> mon_nom_flexible

Vous pouvez assigner mon_nom_flexible à tout type d'objet, et Python va simplement rouler avec elle.

Lorsque vous comparez Python à C ++, la différence entre les variables et les noms peut être un peu déroutante, mais elle présente d’excellents avantages. La première est qu’en Python, vous n’avez pas de pointeur et vous n’avez jamais besoin de penser aux problèmes entre tas et pile. Vous plongerez dans la gestion de la mémoire un peu plus tard dans cet article.

Des compréhensions

Python a une fonctionnalité de langage appelée comprendre la liste. Bien qu’il soit possible d’émuler les interprétations de liste en C ++, c’est assez délicat. En Python, c’est un outil de base qui est enseigné aux programmeurs débutants.

Une façon de penser à la compréhension de liste est qu’il s’agit d’un initialiseur surchargé de listes, de dict ou de jeux. A partir d'un objet itérable, vous pouvez créer une liste et filtrer ou modifier l'original de la manière suivante:

>>>

>>> [[[[X**2 pour X dans intervalle(5)]
[0, 1, 4, 9, 16]

Ce script commence par l'itérable gamme (5) et crée une liste contenant le carré de chaque élément de l'itérable.

Il est possible d’ajouter des conditions aux valeurs de la première itérable:

>>>

>>> odd_squares = [[[[X**2 pour X dans intervalle(5) si X % 2]
>>> odd_squares
[1, 9]

le si x% 2 à la fin de cette compréhension limite les nombres utilisés de gamme (5) à seulement les impairs.

À ce stade, vous pourriez avoir deux idées:

  1. C'est une astuce de syntaxe puissante qui simplifiera certaines parties de mon code.
  2. Vous pouvez faire la même chose en C ++.

Il est vrai que vous pouvez créer un vecteur des carrés des nombres impairs en C ++, cela signifie généralement un peu plus de code:

std::vecteur<int> odd_squares;
pour (int ii = 0; ii < dix; ++ii) 
    si (ii % 2) 
        odd_squares.repousser(ii)
    

Pour les développeurs issus des langages de style C, la compréhension des listes est l’un des premiers moyens remarquables de pouvoir écrire plus de code Pythonic. De nombreux développeurs commencent à écrire Python avec une structure C ++:

odd_squares = []
pour ii dans intervalle(5):
    si (ii % 2):
        odd_squares.ajouter(ii)

Ceci est parfaitement valide Python. Cependant, il fonctionnera probablement plus lentement et ce n’est pas aussi clair et concis que la compréhension de la liste. Apprendre à utiliser les listes de compréhension accélérera non seulement votre code, mais rendra également votre code plus pythonique et plus facile à lire!

Python std :: algorithmes

C ++ a un riche ensemble d'algorithmes intégrés à la bibliothèque standard. Python a un ensemble similaire de fonctions intégrées qui couvrent le même terrain.

Le premier et le plus puissant d'entre eux est le dans opérateur, qui fournit un test assez lisible pour voir si un élément est inclus dans une liste, un ensemble ou un dictionnaire:

>>>

>>> X = [[[[1, 3, 6, 193]
>>> 6 dans X
Vrai
>>> 7 dans X
Faux
>>> y =  'Jim' : 'gris', 'Zoé' : 'blond', 'David' : 'marron' 
>>> 'Jim' dans y
Vrai
>>> 'Fred' dans y
Faux
>>> 'gris' dans y
Faux

Notez que le dans opérateur, lorsqu'il est utilisé sur des dictionnaires, teste uniquement les clés, pas les valeurs. Ceci est démontré par le test final, 'gris' dans y.

dans peut être combiné avec ne pas pour une syntaxe assez lisible:

si prénom ne pas dans y:
    impression(F"prénom    pas trouvé")

La prochaine étape dans votre défilé d’opérateurs intégrés Python est tout. C'est une fonction booléenne qui retourne Vrai si un élément de l'itérable donné est évalué à Vrai. Cela peut sembler un peu ridicule jusqu'à ce que vous vous souveniez de la compréhension de votre liste! La combinaison de ces deux peut produire une syntaxe claire et puissante pour de nombreuses situations:

>>>

>>> my_big_list = [[[[dix, 23, 875]
>>> my_small_list = [[[[1, 2, 8]
>>> tout([[[[X < 3 pour X dans my_big_list])
Faux
>>> tout([[[[X < 3 pour X dans my_small_list])
Vrai

Enfin, vous avez tout, qui est semblable à tout. Cela retourne Vrai seulement si vous l'avez devinétout des éléments dans l'iterable sont Vrai. Là encore, la combinaison de ces éléments avec les interprétations de liste produit une fonctionnalité de langage puissante:

>>>

>>> list_a = [[[[1, 2, 9]
>>> list_b = [[[[1, 3, 9]
>>> tout([[[[X % 2 pour X dans list_a])
Faux
>>> tout([[[[X % 2 pour X dans list_b])
Vrai

tout et tout peut couvrir une grande partie du même terrain où les développeurs C ++ chercheraient à std :: find ou std :: find_if.

Avant de passer à la saisie de variables, mettons à jour votre tableau de comparaison Python vs C ++:

Fonctionnalité Python C ++
Exécution plus rapide X
Exécution multiplateforme X
Variables de type unique X
Variables de type multiple X
Des compréhensions X
Riche ensemble d'algorithmes intégrés X X

OK, vous êtes maintenant prêt à examiner le typage des variables et des paramètres. Allons-y!

Saisie statique vs saisie dynamique

L’utilisation des types de données est un autre sujet important lorsque vous comparez Python à C ++. C ++ est un langage typé statiquement, alors que Python est typé dynamiquement. Voyons ce que cela signifie.

Dactylographie statique

C ++ est typé statiquement, ce qui signifie que chaque variable que vous utilisez dans votre code doit avoir un type de données spécifique, tel que int, carboniser, flotte, et ainsi de suite. Vous ne pouvez affecter que des valeurs du type correct à une variable, à moins que vous ne sautiez à travers certaines étapes.

Cela présente des avantages à la fois pour le développeur et le compilateur. Le développeur a l'avantage de savoir à l'avance le type d'une variable particulière et, par conséquent, les opérations autorisées. Le compilateur peut utiliser les informations de type pour optimiser le code, en le rendant plus petit, plus rapide ou les deux.

Cette connaissance préalable a cependant un coût. Les paramètres passés dans une fonction doivent correspondre au type attendu par la fonction, ce qui peut réduire la flexibilité et l'utilité potentielle du code.

Duck Typing

Le typage dynamique est souvent appelé canard en tapant. C’est un nom étrange, et vous en lirez plus dans une minute! Mais commençons par un exemple. Cette fonction prend un objet fichier et lit les dix premières lignes:

def read_ten(objet_fichier):
    pour numéro de ligne dans intervalle(dix):
        X = objet_fichier.readline()
        impression(F"numéro de ligne    = x.strip () ")

Pour utiliser cette fonction, vous allez créer un objet fichier et le transmettre:

avec ouvrir("types.py") comme F:
    read_ten(F)

Cela montre comment fonctionne la conception de base de la fonction. Bien que cette fonction ait été décrite comme "lisant les dix premières lignes d’un objet fichier", rien dans Python n’exige que objet_fichier être un fichier. Tant que l'objet est passé dans les supports .readline (), l'objet peut être de tout type:

classe canard():
    def readline(soi):
        revenir "charlatan"

mon_duck = canard()
read_ten(mon_duck)

Appel read_ten () avec un canard objet produit:

0 = charlatan
1 = charlatan
2 = charlatan
3 = charlatan
4 = charlatan
5 = charlatan
6 = charlatan
7 = charlatan
8 = charlatan
9 = charlatan

C'est l'essence de frappe de canard. Le proverbe dit: «Si ça ressemble à un canard, si on nage comme un canard et si on rigole comme un canard, alors ça est un canard."

En d’autres termes, si l’objet possède les méthodes nécessaires, il est acceptable de le transmettre, quel que soit le type de l’objet. Duck ou typage dynamique vous donne une énorme flexibilité, car il permet d'utiliser n'importe quel type lorsqu'il rencontre les interfaces requises.

Cependant, il y a un problème ici. Qu'advient-il si vous passez dans un objet qui n'est pas répondre à l'interface requise? Par exemple, si vous transmettez un numéro à read_ten (), comme ça: read_ten (3)?

Cela provoque une exception. À moins que vous ne détectiez l'exception, votre programme explose avec une trace:

Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
  
  
  
  Fichier "duck_test.py", ligne 4, dans read_ten
    X = objet_fichier.readline()
AttributeError: L'objet 'int' n'a pas d'attribut 'readline'

La frappe dynamique peut être un outil assez puissant, mais comme vous pouvez le constater, vous devez faire preuve de prudence lorsque vous l’utilisez.

Passons maintenant à une fonctionnalité qui tire parti du typage dynamique de Python: les modèles.

Modèles

Python n’a pas de modèles comme C ++, mais il n’en a généralement pas besoin. En Python, tout est une sous-classe d'un type de base unique. C'est ce qui vous permet de créer des fonctions de frappe de canard comme celles ci-dessus.

Le système de templates en C ++ est assez puissant et peut vous faire économiser beaucoup de temps et d’efforts. Cependant, cela peut également être source de confusion et de frustration, car les erreurs de compilation dans les modèles peuvent vous laisser perplexe.

Pouvoir utiliser la frappe à la place des modèles facilite grandement certaines choses. Mais cela aussi peut causer des problèmes difficiles à détecter. Comme dans toutes les décisions complexes, vous comparez Python à C ++.

Vérification de type

La communauté Python a récemment suscité beaucoup d’intérêt et de discussions sur la vérification de type statique en Python. Des projets tels que mypy ont soulevé la possibilité d'ajouter une vérification de type pré-exécution à des endroits spécifiques de la langue. Cela peut être très utile pour gérer les interfaces entre des portions de gros packages ou des API spécifiques.

Cela aide à remédier à l’un des inconvénients de la frappe au canard. Pour les développeurs utilisant une fonction, il est utile qu’ils comprennent parfaitement ce que chaque paramètre doit être. Cela peut être utile dans les grandes équipes de projet où de nombreux développeurs ont besoin de communiquer via des API.

Une fois encore, examinons le tableau de comparaison Python vs C ++:

Fonctionnalité Python C ++
Exécution plus rapide X
Exécution multiplateforme X
Variables de type unique X
Variables de type multiple X
Des compréhensions X
Riche ensemble d'algorithmes intégrés X X
Dactylographie statique X
Dactylographie dynamique X

Vous êtes maintenant prêt à passer aux différences de programmation orientée objet.

Programmation orientée objet

Comme C ++, Python prend en charge un modèle de programmation orienté objet. Bon nombre des concepts que vous avez appris en C ++ sont reportés dans Python. Vous devrez toujours prendre des décisions concernant l'héritage, la composition et l'héritage multiple.

Similitudes

L'héritage entre les classes fonctionne de manière similaire dans Python vs C ++. Une nouvelle classe peut hériter des méthodes et des attributs d’une ou de plusieurs classes de base, comme vous l’avez vu en C ++. Certains détails sont toutefois un peu différents.

Les classes de base n'ont pas leur constructeur appelé automatiquement comme elles le font en C ++. Cela peut être déroutant lorsque vous changez de langue.

L'héritage multiple fonctionne également en Python, et il possède autant de bizarreries et de règles étranges qu'en C ++.

De même, vous pouvez également utiliser la composition pour créer des classes, dans lesquelles des objets d'un type contiennent d'autres types. Considérant que tout est un objet en Python, cela signifie que les classes peuvent contenir n'importe quoi d'autre dans le langage.

Différences

Il existe toutefois certaines différences lorsque vous comparez Python et C ++. Les deux premiers sont liés.

La première différence est que Python n'a pas de concept de modificateurs d'accès pour les classes. Tout dans un objet de classe est public. La communauté Python a développé une convention selon laquelle tout membre d'une classe commençant par un trait de soulignement unique est traité comme privé. Cela n’est nullement imposé par la langue, mais cela semble assez bien fonctionner.

Le fait que tous les membres de la classe et toutes les méthodes soient publics dans Python conduit à la deuxième différence: Python a un support d'encapsulation bien plus faible que C ++.

Comme mentionné précédemment, la convention de soulignement unique fait que cette question est beaucoup moins problématique dans les bases de code pratiques que dans un sens théorique. En général, tout utilisateur qui enfreint cette règle et qui dépend du fonctionnement interne d'une classe pose des problèmes.

Surcharges d’opérateurs vs méthodes de Dunder

En C ++, vous pouvez ajouter surcharge de l'opérateur. Ils vous permettent de définir le comportement d’opérateurs syntaxiques spécifiques (comme ==) pour certains types de données. Généralement, ceci est utilisé pour ajouter une utilisation plus naturelle de vos classes. Pour le == opérateur, vous pouvez définir exactement ce que cela signifie pour deux objets d'une classe d'être égaux.

Une différence qui prend beaucoup de temps à comprendre pour certains développeurs est de savoir comment pallier le manque de surcharge d’opérateurs dans Python. C’est formidable que les objets Python fonctionnent tous dans les conteneurs standard, mais si vous voulez que le == opérateur pour faire une comparaison profonde entre deux objets de votre nouvelle classe? En C ++, vous créez un opérateur == () dans votre classe et faites la comparaison.

Python a une structure similaire qui est utilisée assez régulièrement dans le langage: méthodes Dunder. Les méthodes Dunder portent leur nom car elles commencent et finissent toutes par un double soulignement, ou «d-under».

La plupart des fonctions intégrées qui agissent sur les objets en Python sont gérées par des appels aux méthodes dunder de cet objet. Pour votre exemple ci-dessus, vous pouvez ajouter __eq __ () à votre classe de faire la comparaison de votre choix:

classe MyFancyComparisonClass():
    def __eq__(soi, autre):
        revenir Vrai

Cela produit une classe qui se compare de la même manière que toute autre instance de sa classe. Pas particulièrement utile, mais cela montre bien le problème.

Un grand nombre de méthodes dunder sont utilisées dans Python et les fonctions intégrées les utilisent largement. Par exemple, ajouter __lt __ () permettra à Python de comparer l’ordre relatif de deux de vos objets. Cela signifie que non seulement le < opérateur travaille maintenant, mais que >, <=, et > = fonctionnera également aussi bien.

Mieux encore, si vous avez plusieurs objets de votre nouvelle classe dans une liste, vous pouvez alors utiliser triés () sur la liste et ils seront triés en utilisant __lt __ ().

Une fois encore, examinons le tableau de comparaison Python vs C ++:

Fonctionnalité Python C ++
Exécution plus rapide X
Exécution multiplateforme X
Variables de type unique X
Variables de type multiple X
Des compréhensions X
Riche ensemble d'algorithmes intégrés X X
Dactylographie statique X
Dactylographie dynamique X
Encapsulation stricte X

Maintenant que vous avez vu le codage orienté objet dans les deux langages, voyons comment Python et C ++ gèrent ces objets en mémoire.

Gestion de la mémoire

L’une des différences les plus importantes, lorsque vous comparez Python à C ++, réside dans la façon dont elles gèrent la mémoire. Comme vous l’avez vu dans la section sur les variables en C ++ et les noms de Python, Python n’a pas de pointeur et ne vous permet pas non plus de manipuler directement la mémoire. Bien que vous souhaitiez parfois avoir ce niveau de contrôle, la plupart du temps, ce n’est pas nécessaire.

Abandonner le contrôle direct des emplacements mémoire présente quelques avantages. Vous n'avez pas à vous soucier de la propriété de la mémoire ni à vous assurer que cette mémoire est libérée une fois (et une seule fois) après son affectation. En outre, vous n'avez jamais à vous soucier de savoir si un objet a été alloué ou non sur la pile, ce qui a tendance à faire trébucher les développeurs C ++ débutants.

Python gère toutes ces questions pour vous. Tout faire en Python est une classe dérivée de Python. objet. Cela permet à l'interpréteur Python d'implémenter le comptage de références comme moyen de garder trace des objets encore en cours d'utilisation et des objets pouvant être libérés.

Ce confort a un prix, bien sûr. Pour libérer des objets de mémoire alloués pour vous, Python aura parfois besoin d'exécuter ce qu'on appelle un Éboueur, qui trouve des objets de mémoire inutilisés et les libère.

Python utilise deux outils pour libérer de la mémoire:

  1. Le collecteur de comptage de références
  2. Le collectionneur générationnel

Examinons chacun d’eux individuellement.

Collecteur de comptage de références

Le collecteur de comptage de références est fondamental pour l'interpréteur Python standard et est toujours en cours d'exécution. Cela fonctionne en gardant une trace de combien de fois un bloc de mémoire donné (qui est toujours un Python objet) est associé à un nom pendant l'exécution de votre programme. De nombreuses règles décrivent le moment où le compte de référence est incrémenté ou décrémenté, mais un exemple de cas peut clarifier:

>>>

    1 >>> X = 'Une longue ficelle'
    2 >>> y = X
    3 >>> del X
    4 >>> del y

Dans l'exemple ci-dessus, la ligne 1 crée un nouvel objet contenant la chaîne. "Une longue ficelle". Il place ensuite le nom X sur cet objet, en augmentant le nombre de références de l'objet à 1:

Un objet Python avec un nombre de références égal à un.

Sur la ligne 2, il attribue y pour nommer le même objet, ce qui augmentera le nombre de références à 2:

Un objet Python avec un nombre de références de deux.

Quand vous appelez del avec X à la ligne 3, vous supprimez l’une des références à l’objet, ramenant le compte à 1:

Deux objets Python, chacun avec un nombre de références égal à un.

Enfin, lorsque vous supprimez y, référence finale à l’objet, son décompte de références tombe à zéro et il peut être libéré par le garbage collector qui compte les références. Il peut ou ne peut pas être libéré immédiatement à ce stade, mais généralement, cela ne devrait pas avoir d’importance pour le développeur:

L'objet Python None avec un nombre de références de deux et un autre objet Python avec un nombre de références de zéro.

Bien que cela vous permette de trouver et de libérer de nombreux objets à libérer, il existe quelques situations que vous ne rencontrerez pas. Pour cela, vous avez besoin du récupérateur de déchets générationnel.

Ramasse-miettes générationnel

Un des gros trous du schéma de comptage de références est que votre programme peut créer un cycle de références, où object UNE a une référence à object B, qui a une référence à object UNE. Il est tout à fait possible que cette situation se produise et que votre code ne contienne aucun objet. Dans ce cas, aucun des objets n'atteindra jamais un compte de référence de 0.

le éboueur de génération implique un algorithme complexe qui dépasse le cadre de cet article, mais il trouvera certains de ces cycles de référence orphelins et les libérera pour vous. Il fonctionne occasionnellement et est contrôlé par les paramètres décrits dans la documentation. L'un de ces paramètres consiste à désactiver complètement ce ramasse-miettes.

Quand vous ne voulez pas ramasser les ordures

Lorsque vous comparez Python à C ++, comme lorsque vous comparez deux outils, chaque avantage est assorti d’un compromis. Python ne nécessite pas de gestion de mémoire explicite, mais il passe parfois plus de temps que prévu à la récupération de place. L’inverse est vrai pour C ++: votre programme aura des temps de réponse cohérents, mais vous devrez déployer davantage d’efforts pour gérer la mémoire.

Dans de nombreux programmes, la récupération occasionnelle des ordures n'a pas d'importance. Si vous écrivez un script qui ne dure que 10 secondes, il est peu probable que vous remarquiez la différence. Toutefois, certaines situations nécessitent des temps de réponse cohérents. Les systèmes en temps réel sont un bon exemple dans lequel il peut être essentiel de réagir à un matériel informatique dans un laps de temps déterminé pour le bon fonctionnement de votre système.

Parmi les systèmes pour lesquels Python est un mauvais choix de langage, les systèmes avec des exigences en temps réel difficiles Avoir un système étroitement contrôlé où vous êtes certain du timing est une bonne utilisation du C ++. Tels sont les types de problèmes à prendre en compte lorsque vous choisissez la langue d’un projet.

Il est temps de mettre à jour votre diagramme Python vs C ++:

Fonctionnalité Python C ++
Exécution plus rapide X
Exécution multiplateforme X
Variables de type unique X
Variables de type multiple X
Des compréhensions X
Riche ensemble d'algorithmes intégrés X X
Dactylographie statique X
Dactylographie dynamique X
Encapsulation stricte X
Contrôle direct de la mémoire X
Collecte des ordures X

Threading, multitraitement et async IO

Les modèles de simultanéité en C ++ et Python sont similaires, mais ils ont des résultats et des avantages différents. Les deux langues prennent en charge les opérations de threading, de multitraitement et Async IO. Regardons chacun de ceux-ci.

Filetage

Bien que C ++ et Python intègrent des threads au langage, les résultats peuvent être très différents, en fonction du problème que vous résolvez. Le threading est souvent utilisé pour résoudre les problèmes de performances. En C ++, le threading peut fournir une accélération générale pour les problèmes liés aux calculs et aux E / S, car les threads peuvent tirer pleinement parti des cœurs d'un système multiprocesseur.

Python, d’autre part, a fait un compromis sur la conception pour utiliser le Verrou d'interprète global, ou le GIL, pour simplifier son implémentation de threading. GIL présente de nombreux avantages, mais l'inconvénient est qu'un seul thread s'exécutera à la fois, même s'il y a plusieurs cœurs.

Si votre problème est lié aux entrées-sorties, comme l'extraction simultanée de plusieurs pages Web, cette limitation ne vous dérangera pas du tout. Vous apprécierez le modèle de threading plus simple de Python et les méthodes intégrées pour les communications inter-thread. Toutefois, si votre problème est lié au processeur, la GIL limitera vos performances à celles d’un processeur unique. Heureusement, la bibliothèque de traitement multiple de Python a une interface similaire à celle de la bibliothèque de threads.

Multitraitement

La prise en charge du multitraitement en Python est intégrée à la bibliothèque standard. Son interface épurée vous permet d’activer plusieurs processus et de partager des informations entre eux. Vous pouvez créer un pool de processus et les répartir à l'aide de plusieurs techniques.

Bien que Python utilise toujours des primitives de système d'exploitation similaires pour créer les nouveaux processus, une grande partie de la complication de bas niveau est masquée par le développeur.

C ++ s'appuie sur fourchette() fournir un support multitraitement. Bien que cela vous donne un accès direct à tous les contrôles et problèmes liés à la création de processus multiples, il est également beaucoup plus complexe.

Async IO

Bien que Python et C ++ prennent en charge les routines d’E / S asynchrones, elles sont gérées différemment. En C ++, le std :: async méthodes sont susceptibles d'utiliser threading pour atteindre la nature Async IO de leurs opérations. En Python, le code IO Async ne s'exécutera que sur un seul thread.

Il y a des compromis ici aussi. L'utilisation de threads distincts permet au code IO Async C ++ de s'exécuter plus rapidement sur les problèmes liés aux calculs. Les tâches Python utilisées dans son implémentation Async IO sont plus légères. Il est donc plus rapide d’en transformer un grand nombre pour gérer les problèmes liés aux E / S.

Votre tableau comparatif Python vs C ++ reste inchangé pour cette section. Les deux langues prennent en charge une gamme complète d'options de concurrence, avec des compromis variables entre rapidité et commodité.

Problèmes divers

Si vous comparez Python à C ++ et envisagez d’ajouter Python à votre toolbelt, vous devez tenir compte de quelques autres facteurs. Bien que votre éditeur ou IDE actuel fonctionne certainement pour Python, vous souhaiterez peut-être ajouter certaines extensions ou modules de langue. Il convient également de jeter un coup d’œil à PyCharm, car elle est spécifique à Python.

Plusieurs projets C ++ ont des liaisons Python. Things like Qt, WxWidgets, and many messaging APIs having multiple-language bindings.

If you want to embed Python in C++, then you can use the Python/C API.

Finally, there are several methods for using your C++ skills to extend Python and add functionality, or to call your existing C++ libraries from within your Python code. Tools like CTypes, Cython, CFFI, Boost.Python and Swig can help you combine these languages and use each for what it’s best at.

Summary: Python vs C++

You’ve spent some time reading and thinking about the differences between Python vs C++. While Python has easier syntax and fewer sharp edges, it’s not a perfect fit for all problems. You’ve looked at the syntax, memory management, processing, and several other aspects of these two languages.

Let’s take a final look at your Python vs C++ comparison chart:

Fonctionnalité Python C++
Faster Execution X
Cross-Platform Execution X
Single-Type Variables X
Multiple-Type Variables X
Comprehensions X
Rich Set of Built-In Algorithms X X
Static Typing X
Dynamic Typing X
Strict Encapsulation X
Direct Memory Control X
Garbage Collection X

If you’re comparing Python vs C++, then you can see from your chart that this is not a case where one is better than the other. Each of them is a tool that’s well crafted for various use cases. Just like you don’t use a hammer for driving screws, using the right language for the job will make your life easier!

Conclusion

Félicitations! You’ve now seen some of the strengths and weaknesses of both Python and C++. You’ve learned some of the features of each language and how they are similar.

You’ve seen that C++ is great when you want:

  • Fast execution speed (potentially at the cost of development speed)
  • Complete control of memory

Conversely, Python is great when you want:

  • Fast development speed (potentially at the cost of execution speed)
  • Managed memory

You’re now ready to make a wise language choice when it comes to your next project!