Python vs C ++: sélectionner le bon outil pour le travail

Python vs C ++: sélectionner le bon outil pour le travail

Êtes-vous un développeur C comparant Python à C? Vous regardez Python et vous vous demandez de quoi il s'agit? Vous demandez-vous comment Python se compare aux concepts que vous connaissez déjà? Ou peut-être avez-vous un pari sur qui gagnerait si vous enfermiez C ++ et Python dans une cage et les laissiez s'affronter? Alors cet article est fait pour vous!

In this article, you’ll learn about:

  • Différences et similitudes lorsque vous comparez Python vs C ++

  • Moments où Python pourrait être un meilleur choix pour un problème et vice versa

  • Ressources vers lesquelles vous tourner lorsque vous avez des questions tout en apprenant Python

Cet article est destiné 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 plus, ainsi que C11 ou plus.

Plongeons-nous dans Python vs C ++!

Free Bonus:Click here to get access to a chapter from Python Tricks: The Book qui vous montre les meilleures pratiques de Python avec des exemples simples que vous pouvez appliquer instantanément pour écrire du code + Pythonic plus beau.

Comparaison des langages: Python vs C ++

Souvent, vous trouverez des articles qui vantent les vertus d'un langage de programmation sur un autre. Très souvent, ils se consacrent à la promotion d'une langue en dégradant l'autre. Ce n'est pas ce type d'article.

Lorsque vous comparez Python à C ++, n'oubliez pas que ce sont deux outils et qu'ils ont tous deux des utilisations pour des problèmes différents. Pensez à comparer un marteau et un tournevis. Vouscould utilisez un tournevis pour enfoncer les clous, et vouscould utilisez un marteau pour forcer les vis, mais aucune expérience ne sera aussi efficace.

Il est important d'utiliser le bon outil pour le travail. Dans cet article, vous découvrirez les fonctionnalités de Python et C qui font de chacun d'eux le bon choix pour certains types de problèmes. Donc, ne considérez pas le "vs" dans Python vs C comme signifiant "contre". Pensez-y 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 produit un exécutable. L'exécutable est un fichier distinct qui peut ensuite être exécuté en tant que programme autonome:

Compiling a C++ program for windows.

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

Compiling a C++ program on three operating systems.

Vous devrez probablement modifier votre code C ++ pour qu'il s'exécute également sur ces différents systèmes.

Python, en revanche, utilise un processus différent. Maintenant, rappelez-vous que vous allez regarderCPython qui est l'implémentation standard pour le langage. À moins que vous ne fassiez 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 compile enbytecode au lieu du code machine natif. Bytecode est le code d'instruction natif pour lesPython virtual machine. Pour accélérer les exécutions suivantes de votre programme, Python stocke le bytecode dans les fichiers.pyc:

Python compiles a py file into a pyc file.

Si vous utilisez Python 2, vous trouverez ces fichiers à côté des fichiers.py. Pour Python 3, vous les trouverez dans un répertoire__pycache__.

Le bytecode généré ne s'exécute pas nativement sur votre processeur. Au lieu de cela, il est géré par la machine virtuelle Python. Ceci est similaire à la machine virtuelle Java ou à l'environnement d'exécution commun .NET. L'exécution initiale 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 compiles a py file into a pyc file and then executes it.

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

Python executes a pyc file.

L'interprétation du code va être plus lente que l'exécution du code natif directement sur le matériel. Alors pourquoi Python fonctionne-t-il de cette façon? Eh bien, interpréter le code dans une machine virtuelle signifie que 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 s'exécutera sur n'importe quelle machine disposant de Python.

Note: CPython est écrit en C, donc il peut fonctionner sur la plupart des systèmes qui ont un compilateur C.

Une autre caractéristique de cette prise en charge multiplateforme est que la vaste bibliothèque standard de Python est écrite pour fonctionner sur tous les systèmes d'exploitation.

L'utilisation depathlib, par 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 préoccuper dans votre programme Python!

Avant de poursuivre, commençons à suivre un graphique de comparaison Python vs C ++. Lorsque vous couvrirez 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 vu les différences de temps d'exécution lorsque vous comparez Python vs C ++, examinons les spécificités de la syntaxe des langages.

Différences de syntaxe

Python et C ++ partagent de nombreuses similitudes syntaxiques, mais il y a quelques domaines à discuter:

  • Espace blanc

  • Expressions booléennes

  • Variables et pointeurs

  • Compréhensions

Commençons par le plus controversé en premier: 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 un espace blanc pour marquer la portée. Cela signifie que le corps d'un bloc `+ if +` ou d'une autre structure similaire est indiqué par le niveau d'indentation. C utilise des accolades ({}) pour indiquer la même idée.

Alors que le lexer Python accepte n'importe quel espace tant que vous êtes cohérent,PEP8 (lesofficial style guide pour Python) spécifie 4 espaces pour chaque niveau d'indentation. La plupart des éditeurs peuvent être configurés pour le faire automatiquement.

Il y a déjà eu une énorme quantité dewriting,shouting etranting à propos des règles d'espaces blancs de Python, alors passons au-delà de ce problème et passons à d'autres questions.

Au lieu de s'appuyer sur un marqueur lexical comme; pour terminer chaque instruction, Python utilise la fin de la ligne. Si vous devez étendre une instruction sur une seule ligne, vous pouvez utiliser la barre oblique inverse (\) pour l'indiquer. (Notez que si vous êtes à l'intérieur d'un ensemble de 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 aiment que vous n'ayez pas à taper d'accolades et de points-virgules. Certains développeurs C ++ détestent se fier à la mise en forme. Apprendre à être à l'aise avec les deux est votre meilleur choix.

Maintenant que vous avez examiné le problème des espaces blancs, passons à celui qui est un peu moins litigieux: les expressions booléennes.

Expressions booléennes

La façon dont vous utiliserezBoolean expressions change légèrement entre Python et C. En C, vous pouvez utiliser des valeurs numériques pour indiquertrue oufalse, en plus des valeurs intégrées. Tout ce qui est évalué à0 est considéré commefalse, tandis que toute autre valeur numérique esttrue.

Python a un concept similaire mais l'étend pour inclure d'autres cas. Les bases sont assez similaires. LePython documentation indique que les éléments suivants sont évalués àFalse:

  • Constantes définies comme fausses:

    • None

    • False

  • Zéros de tout type numérique:

    • 0

    • 0.0

    • 0j

    • Decimal(0)

    • Fraction(0, 1)

  • Séquences vides et collections:

    • ''

    • ()

    • []

    • {}

    • set()

    • range(0)

Tous les autres éléments sont desTrue. Cela signifie qu'une liste vide[] estFalse, alors qu'une liste ne contenant que zéro[0] est toujoursTrue.

La plupart des objets seront évalués àTrue, sauf si l'objet a__bool__() qui renvoieFalse 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 à C dans les opérateurs booléens. Pour commencer, les instructions `+ if +` et `+ while +` ne nécessitent pas les parenthèses environnantes comme elles le font en C. Les parenthèses peuvent aider à la lisibilité, cependant, utilisez donc votre meilleur jugement.

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

Opérateur C ++ Opérateur Python

&&

and

`+

+`

or

!

not

&

&

`+

+`

`+

+`

La plupart des opérateurs sont similaires au C ++, mais si vous voulez rafraîchir, vous pouvez lireOperators and Expressions in Python.

Variables et pointeurs

Lorsque vous commencez à utiliser Python après avoir écrit en C, vous risquez de ne pas trop réfléchir aux variables. Ils semblent fonctionner généralement comme ils le font dans C. Mais ce n'est pas pareil. Alors qu'en C ++ vous utilisez des variables pour référencer des valeurs, en Python vous utilisez des noms.

Note: Pour cette section, où vous examinez les variables et les noms en Python et en C, vous utiliserez * variables * pour C etnames pour Python. Ailleurs, ils seront tous deux appelésvariables.

Tout d'abord, revenons un peu en arrière et examinons plus largement lesobject model de Python.

En Python,everything est un objet. Les nombres sont conservés dans des objets. Les modules sont contenus dans des objets. Tant l'objet d'une classeandque la classe elle-même sont des objets. Les fonctions sont aussi des objets:

>>>

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

>>> def sayHi(name):
...      print(f'Hello, {name}')
...
>>> a_function_object = sayHi
>>> a_function_object

L'appel delist() crée un nouvel objet de liste, que vous affectez àa_list_object. L'utilisation du nom de la classelist à elle seule place une étiquette sur l'objet de classe. Vous pouvez également placer une nouvelle étiquette sur une fonction. Il s'agit d'un outil puissant et, comme tous les outils puissants, il peut être dangereux. (Je vous regarde, M. Tronçonneuse.)

Note: Le code ci-dessus est affiché en cours d'exécution dans unREPL, qui signifie «Read, Eval, Print Loop». Cet environnement interactif est fréquemment utilisé pour tester des idées en Python et dans d'autres langages interprétés.

Si vous tapezpython à une invite de commande, cela affichera une REPL où vous pourrez commencer à taper du code et à essayer des choses par vous-même!

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

int an_int;
float 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:

>>>

>>> my_flexible_name = 1
>>> my_flexible_name
1
>>> my_flexible_name = 'This is a string'
>>> my_flexible_name
'This is a string'
>>> my_flexible_name = [3, 'more info', 3.26]
>>> my_flexible_name
[3, 'more info', 3.26]
>>> my_flexible_name = print
>>> my_flexible_name

Vous pouvez affectermy_flexible_name à n'importe quel type d'objet, et Python roulera simplement avec lui.

Lorsque vous comparez Python vs C ++, la différence entre les variables et les noms peut être un peu déroutante, mais elle présente d'excellents avantages. Premièrement, en Python, vous n’avez paspointers, et vous n’avez jamais besoin de penser aux problèmes de tas et de pile. Vous plongerez dans la gestion de la mémoire un peu plus loin dans cet article.

Compréhensions

Python a une fonctionnalité de langage appeléelist comprehensions. Bien qu'il soit possible d'émuler des compréhensions de liste en C ++, c'est assez délicat. En Python, ils sont un outil de base qui est enseigné aux programmeurs débutants.

Une façon de penser à la compréhension des listes est qu’elles sont comme un initialiseur surchargé pour les listes, les dictés ou les ensembles. Étant donné un objet itérable, vous pouvez créer une liste et filtrer ou modifier l'original au fur et à mesure:

>>>

>>> [x**2 for x in range(5)]
[0, 1, 4, 9, 16]

Ce script commence par l'itérablerange(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 du premier itérable:

>>>

>>> odd_squares = [x**2 for x in range(5) if x % 2]
>>> odd_squares
[1, 9]

Leif x % 2 à la fin de cette compréhension limite les nombres utilisés derange(5) aux seuls impairs.

À ce stade, vous pourriez avoir deux pensé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 ++.

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

std::vector odd_squares;
for (int ii = 0; ii < 10; ++ii) {
    if (ii % 2) {
        odd_squares.push_back(ii);
    }
}

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

odd_squares = []
for ii in range(5):
    if (ii % 2):
        odd_squares.append(ii)

C'est Python parfaitement valide. Elle s'exécutera probablement plus lentement, cependant, et elle n'est pas aussi claire et concise que la compréhension de la liste. Apprendre à utiliser les listes de compréhension accélérera non seulement votre code, mais il rendra également votre code plus Pythonic et plus facile à lire!

Note: Lorsque vous lisez sur Python, vous verrez fréquemment le motPythonic utilisé pour décrire quelque chose. C'est juste un terme que la communauté utilise pour décrire un code propre, élégant et qui semble avoir été écrit par un Jedi Python.

std::algorithms de Python

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

Le premier et le plus puissant d'entre eux est lein operator, qui fournit un test assez lisible pour voir si un élément est inclus dans unlist,set oudictionary:

>>>

>>> x = [1, 3, 6, 193]
>>> 6 in x
True
>>> 7 in x
False
>>> y = { 'Jim' : 'gray', 'Zoe' : 'blond', 'David' : 'brown' }
>>> 'Jim' in y
True
>>> 'Fred' in y
False
>>> 'gray' in y
False

Notez que l'opérateurin, lorsqu'il est utilisé sur des dictionnaires, ne teste que les clés, pas les valeurs. Ceci est montré par le test final,'gray' in y.

in peut être combiné avecnot pour une syntaxe assez lisible:

if name not in y:
    print(f"{name} not found")

Le prochain dans votre défilé d'opérateurs intégrés Python estany. Il s'agit d'une fonction booléenne qui renvoieTrue si un élément de l'itérable donné est évalué àTrue. Cela peut sembler un peu idiot jusqu'à ce que vous vous souveniez de vos listes de compréhension! La combinaison de ces deux peut produire une syntaxe claire et puissante pour de nombreuses situations:

>>>

>>> my_big_list = [10, 23, 875]
>>> my_small_list = [1, 2, 8]
>>> any([x < 3 for x in my_big_list])
False
>>> any([x < 3 for x in my_small_list])
True

Enfin, vous avezall, qui est similaire àany. Cela renvoieTrueonly si - vous l'avez deviné -all des éléments de l'itérable sontTrue. Encore une fois, combiner cela avec des compréhensions de liste produit une puissante fonctionnalité de langage:

>>>

>>> list_a = [1, 2, 9]
>>> list_b = [1, 3, 9]
>>> all([x % 2 for x in list_a])
False
>>> all([x % 2 for x in list_b])
True

any etall peuvent couvrir une grande partie du même terrain où les développeurs C ++ se tourneraient versstd::find oustd::find_if.

Note: Dans les exemplesany etall ci-dessus, vous pouvez supprimer les crochets ([]) sans aucune perte de fonctionnalité. (par exemple:all(x % 2 for x in list_a)) Cela utilisegenerator expressions qui, bien que très pratique, sortent du cadre de cet article.

Avant de passer au typage des 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 types multiples

x

Compréhensions

x

Ensemble riche d'algorithmes intégrés

x

x

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

Typage vs typage dynamique

Un autre sujet important lorsque vous comparez Python et C est l’utilisation des types de données. C est un langage typé statiquement, tandis que Python est typé dynamiquement. Voyons ce que cela signifie.

Typage 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 queint,char,float, etc. Vous ne pouvez affecter des valeurs du type correct à une variable que si vous sautez dans certains cercles.

Cela présente certains avantages pour le développeur et le compilateur. Le développeur a l'avantage de savoir à l'avance quel est le type d'une variable particulière et donc quelles opérations sont autorisées. Le compilateur peut utiliser les informations de type pour optimiser le code, le rendant plus petit, plus rapide ou les deux.

Cette connaissance avancée 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.

Dactylographie de canard

La saisie dynamique est souvent appeléeduck typing.. C'est un nom étrange, et vous en apprendrez plus à ce sujet dans une minute! Mais d'abord, commençons par un exemple. Cette fonction prend un objet fichier et lit les dix premières lignes:

def read_ten(file_like_object):
    for line_number in range(10):
        x = file_like_object.readline()
        print(f"{line_number} = {x.strip()}")

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

with open("types.py") as f:
    read_ten(f)

Cela montre comment fonctionne la conception de base de la fonction. Bien que cette fonction ait été décrite comme «la lecture des dix premières lignes d'un objet fichier», il n'y a rien en Python qui exige quefile_like_objectbe un fichier. Tant que l'objet passé dans prend en charge.readline(), l'objet peut être de n'importe quel type:

class Duck():
    def readline(self):
        return "quack"

my_duck = Duck()
read_ten(my_duck)

L'appel deread_ten() avec un objetDuck produit:

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

C'est l'essence deduck typing. Le dicton dit: «Si ça ressemble à un canard, nage comme un canard et charlatan comme un canard, alors c'est probablementisun 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. Le typage canard ou dynamique vous donne une énorme flexibilité, car il permet à tout type d'être utilisé là où il rencontre les interfaces requises.

Cependant, il y a un problème ici. Que se passe-t-il si vous transmettez un objet dontdoesn’t répond à l'interface requise? Par exemple, que se passe-t-il si vous passez un nombre àread_ten(), comme ceci:read_ten(3)?

Il en résulte une exception levée. À moins que vous ne rencontriez l'exception, votre programme explosera avec untraceback:

Traceback (most recent call last):
  File "", line 1, in 
  File "duck_test.py", line 4, in read_ten
    x = file_like_object.readline()
AttributeError: 'int' object has no attribute 'readline'

La frappe dynamique peut être un outil assez puissant, mais comme vous pouvez le voir, vous devez faire preuve de prudence lors de son utilisation.

Note: Python et C sont tous deux considérés comme des langages https://stackoverflow.com/a/11328980 (fortement typés]. Bien que C ait un système de type plus fort, les détails de celui-ci ne sont généralement pas importants pour quelqu'un qui apprend Python.

Passons à une fonctionnalité qui profite de la saisie 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 seul type de base. C'est ce qui vous permet de créer des fonctions de frappe de canard comme celles ci-dessus.

Le système de modèles en C ++ vous permet de créer des fonctions ou des algorithmes qui fonctionnent sur plusieurs types différents. C'est assez puissant et peut vous faire économiser beaucoup de temps et d'efforts. Cependant, cela peut également être une source de confusion et de frustration, car les erreurs de compilation dans les modèles peuvent vous laisser perplexe.

Pouvoir utiliser la saisie de canard au lieu de modèles facilite beaucoup les choses. Mais cela peut également entraîner des problèmes difficiles à détecter. Comme dans toutes les décisions complexes, il y a des compromis lorsque vous comparez Python vs C ++.

Vérification de type

Récemment, la communauté Python a suscité beaucoup d'intérêt et de discussions sur la vérification de type statique dans Python. Des projets commemypy ont soulevé la possibilité d'ajouter une vérification de type avant l'exécution à des emplacements spécifiques dans la langue. Cela peut être très utile pour gérer les interfaces entre des portions de gros packages ou des API spécifiques.

Il aide à résoudre l'un des inconvénients de la frappe de canard. Pour les développeurs qui utilisent une fonction, cela aide s'ils peuvent comprendre pleinement ce que chaque paramètre doit être. Cela peut être utile sur de grandes équipes de projet où de nombreux développeurs doivent communiquer via des API.

Encore une fois, jetons un œil à 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 types multiples

x

Compréhensions

x

Ensemble riche d'algorithmes intégrés

x

x

Typage 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 https://realpython.com/courses/intro-object-oriented-programming-oop-python/[object-oriented program model]. Beaucoup des mêmes concepts que vous avez appris en C sont transférés dans Python. Vous devrez toujours prendre des décisions concernantinheritance, composition et l'héritage multiple.

Similitudes

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

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

Multiple inheritance fonctionne également en Python, et il a 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, où vous avez des objets d'un type contenant 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 cependant quelques différences lorsque vous comparez Python à 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 seul trait de soulignement est traité comme privé. Ce n'est en aucun cas imposé par la langue, mais cela semble fonctionner assez bien.

Le fait que chaque membre de classe et chaque méthode soit public en Python conduit à la deuxième différence: Python a un support d'encapsulation beaucoup plus faible que C ++.

Comme mentionné, la convention de soulignement unique rend ce problème 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 dépend du fonctionnement interne d'une classe demande des ennuis.

Surcharge d'opérateur vs méthodes Dunder

En C +, vous pouvez ajouter des * surcharges d'opérateurs *. Celles-ci vous permettent de définir le comportement d'opérateurs syntaxiques spécifiques (comme `==`) pour certains types de données. Habituellement, cela est utilisé pour ajouter une utilisation plus naturelle de vos classes. Pour l'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 du temps à certains développeurs est de savoir comment contourner le manque de surcharges d'opérateurs en Python. C'est formidable que les objets Python fonctionnent tous dans l'un des conteneurs standard, mais que faire si vous voulez que l'opérateur== effectue une comparaison approfondie entre deux objets de votre nouvelle classe? En C +, vous créez un `+ opérateur == ()` dans votre classe et effectuez la comparaison.

Python a une structure similaire qui est utilisée de manière assez cohérente dans le langage:dunder methods. Les méthodes de donjon doivent leur nom parce qu'elles commencent et se terminent toutes par un double soulignement, ou «d-under».

De nombreuses fonctions intégrées qui opèrent sur des objets en Python sont gérées par des appels auxdunder methods de cet objet. Pour votre exemple ci-dessus, vous pouvez ajouter__eq__() à votre classe pour faire n'importe quelle comparaison sophistiquée que vous aimez:

class MyFancyComparisonClass():
    def __eq__(self, other):
        return True

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 démontre le point.

Il existe un grand nombre de méthodes de dunder utilisées en Python, et les fonctions intégrées les utilisent largement. Par exemple, l'ajout de__lt__() permettra à Python de comparer l'ordre relatif de deux de vos objets. Cela signifie que non seulement l'opérateur< fonctionnera désormais, mais que>,<= et>= fonctionneront également.

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

Encore une fois, jetons un œil à 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 types multiples

x

Compréhensions

x

Ensemble riche d'algorithmes intégrés

x

x

Typage statique

x

Dactylographie dynamique

x

Encapsulation stricte

x

Maintenant que vous avez vu un 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 plus grandes différences, lorsque vous comparez Python et C, est la façon dont ils gèrent la mémoire. Comme vous l'avez vu dans la section sur les variables dans les noms de C et Python, Python n'a pas de pointeurs et ne vous permet pas non plus de manipuler directement la mémoire. Bien qu'il y ait des moments où vous voulez avoir ce niveau de contrôle, la plupart du temps ce n'est pas nécessaire.

Renoncer au contrôle direct des emplacements de mémoire apporte quelques avantages. Vous n'avez pas à vous soucier de la propriété de la mémoire ou de vous assurer que la mémoire est libérée une fois (et une seule fois) après son allocation. Vous n'avez également jamais à vous soucier de savoir si un objet a été alloué ou non sur la pile ou le tas, ce qui a tendance à déclencher les développeurs C ++ débutants.

Python gère tous ces problèmes pour vous. Pour faire cela, tout en Python est une classe dérivée desobject de Python. Cela permet à l'interpréteur Python d'implémenter le comptage de références comme moyen de garder une trace des objets qui sont encore en cours d'utilisation et qui peuvent être libérés.

Cette commodité a un prix, bien sûr. Pour libérer des objets mémoire alloués pour vous, Python devra parfois exécuter ce qu'on appelle ungarbage collector, qui trouve les objets mémoire inutilisés et les libère.

Note: CPython a unmemory management scheme complexe, ce qui signifie que la libération de mémoire ne signifie pas nécessairement que la mémoire est renvoyée au système d'exploitation.

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

  1. Le collecteur de comptage de référence

  2. Le collectionneur générationnel

Examinons chacun de ces éléments individuellement.

Collecteur de comptage de référence

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 du nombre de fois qu'un bloc de mémoire donné (qui est toujours un Pythonobject) a un nom qui lui est attaché pendant que votre programme est en cours d'exécution. De nombreuses règles décrivent quand le nombre de références est incrémenté ou décrémenté, mais un exemple d'un cas pourrait clarifier:

>>>

 1 >>> x = 'A long string'
 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"A long string". Il place ensuite le nomx sur cet objet, augmentant le nombre de références de l’objet à 1:

A Python object with reference count of one.

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

A Python object with reference count of two.

Lorsque vous appelezdel avecx à la ligne 3, vous supprimez l'une des références à l'objet, en ramenant le nombre à 1:

Two Python objects

Enfin, lorsque vous supprimezy, la référence finale à l'objet, son nombre de références tombe à zéro et il peut être libéré par le ramasse-miettes de comptage de références. Il peut ou non être libéré immédiatement à ce stade, mais en général, cela ne devrait pas avoir d'importance pour le développeur:

The Python None object with reference count of two and another Python object with reference count of zero.

Bien que cela se charge de trouver et de libérer de nombreux objets qui doivent être libérés, il y a quelques situations qu'il ne détectera pas. Pour cela, vous avez besoin du garbage collector générationnel.

Garbage Collector générationnel

L'un des gros trous dans le schéma de comptage de références est que votre programme peut construire un cycle de références, où l'objetA a une référence à l'objetB, qui a une référence à l'objetA. Il est tout à fait possible de rencontrer cette situation et de ne rien avoir dans votre code faisant référence à l'un ou l'autre objet. Dans ce cas, aucun des objets n'atteindra jamais un décompte de référence de 0.

Legenerational garbage collector implique un algorithme complexe qui sort du cadre de cet article, mais il trouvera certains de ces cycles de référence orphelins et les libérera pour vous. Il fonctionne de manière occasionnelle contrôlée par les paramètres décritsin the documentation. L'un de ces paramètres consiste à désactiver complètement ce garbage collector.

Quand vous ne voulez pas de collecte des ordures

Lorsque vous comparez Python et C, comme lorsque vous comparez deux outils, chaque avantage s'accompagne d'un compromis. Python ne nécessite pas de gestion explicite de la mémoire, mais occasionnellement, il passera plus de temps que prévu sur 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 consacrer plus d’efforts à la gestion de la mémoire.

Dans de nombreux programmes, le coup occasionnel de collecte des ordures n'est pas important. Si vous écrivez un script qui ne dure que 10 secondes, il est peu probable que vous remarquiez la différence. Cependant, certaines situations nécessitent des temps de réponse cohérents. Les systèmes en temps réel sont un excellent exemple, où répondre à un élément matériel dans un laps de temps fixe peut être essentiel au bon fonctionnement de votre système.

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

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

Fonctionnalité Python C++

Exécution plus rapide

x

Exécution multiplateforme

x

Variables de type unique

x

Variables de types multiples

x

Compréhensions

x

Ensemble riche d'algorithmes intégrés

x

x

Typage statique

x

Dactylographie dynamique

x

Encapsulation stricte

x

Contrôle direct de la mémoire

x

Collecte des ordures

x

Threading, Multiprocessing et Async IO

Les modèles de concurrence 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. Examinons chacun de ces éléments.

Enfiler

Bien que C et Python aient tous deux des threads intégrés dans le langage, les résultats peuvent être sensiblement différents, en fonction du problème que vous résolvez. Fréquemment, https://realpython.com/intro-to-python-threading/[threading] est 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 sur un système multiprocesseur.

Python, d'autre part, a fait un compromis de conception pour utiliser lesGlobal Interpreter Lock, ou lesGIL, pour simplifier son implémentation de thread. Le GIL présente de nombreux avantages, mais l'inconvénient est qu'un seul thread s'exécutera à la fois, même s'il existe plusieurs cœurs.

Si votre problème est lié aux E / S, comme la récupération de plusieurs pages Web à la fois, cette limitation ne vous dérangera pas le moins du monde. Vous apprécierez le modèle de threading plus simple de Python et les méthodes intégrées pourinter-thread communications. Si votre problème est lié au processeur, cependant, le GIL limitera vos performances à celles d'un seul processeur. Heureusement, la bibliothèque multiprocessing de Python a une interface similaire à sa bibliothèque de threads.

Multiprocessing

La prise en charge deMultiprocessing en Python est intégrée à la bibliothèque standard. Il a une interface propre qui vous permet de faire tourner plusieurs processus et de partager des informations entre eux. Vous pouvez créer un pool de processus et répartir le travail entre eux à l'aide de plusieurs techniques.

Alors 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 cachée au développeur.

C ++ s'appuie surfork() pour assurer la prise en charge du multitraitement. Bien que cela vous donne un accès direct à tous les contrôles et problèmes liés à la création de plusieurs processus, il est également beaucoup plus complexe.

Async IO

Bien que Python et C prennent en charge les routines Async IO, elles sont gérées différemment. En C, les méthodesstd::async sont susceptibles d'utiliser le threading pour atteindre la nature Async IO de leurs opérations. En Python, le code deAsync IOne fonctionnera que sur un seul thread.

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

Votre graphique de comparaison 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 la vitesse et la commodité.

Problèmes divers

Si vous comparez Python vs C ++ et que vous envisagez d'ajouter Python à votre ceinture d'outils, il y a quelques autres choses à considérer. Alors que votre éditeur ou IDE actuel fonctionnera certainement pour Python, vous voudrez peut-être ajouter certaines extensions ou packs de langue. Cela vaut également la peine de jeter un coup d'œil àPyCharm, car il est spécifique à Python.

Plusieurs projets C ++ ont des liaisons Python. Des choses commeQt,WxWidgets et de nombreuses API de messagerie ayant des liaisons dans plusieurs langues.

Si vous voulezembed Python in C++, vous pouvez utiliser lesPython/C API.

Enfin, il existe plusieurs méthodes pour utiliser vos compétences C pour étendre Python et ajouter des fonctionnalités, ou pour appeler vos bibliothèques C existantes à partir de votre code Python. Des outils tels queCTypes,Cython,CFFI,Boost.Python etSwig peuvent vous aider à combiner ces langages et à utiliser chacun pour ce qu'il fait de mieux.

Résumé: Python vs C ++

Vous avez passé un peu de temps à lire et à réfléchir aux différences entre Python et C ++. Bien que Python ait une syntaxe plus facile et moins d'arêtes vives, ce n'est pas un ajustement parfait pour tous les problèmes. Vous avez examiné la syntaxe, la gestion de la mémoire, le traitement et plusieurs autres aspects de ces deux langages.

Jetons un dernier coup d'œil à 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 types multiples

x

Compréhensions

x

Ensemble riche d'algorithmes intégrés

x

x

Typage statique

x

Dactylographie dynamique

x

Encapsulation stricte

x

Contrôle direct de la mémoire

x

Collecte des ordures

x

Si vous comparez Python vs C ++, vous pouvez voir sur votre graphique que ce n'est pas un cas où l'un est meilleur que l'autre. Chacun d'eux est un outil bien conçu pour divers cas d'utilisation. Tout comme vous n'utilisez pas de marteau pour enfoncer des vis, utiliser le bon langage pour le travail vous facilitera la vie!

Conclusion

Félicitations! Vous avez maintenant vu certaines des forces et des faiblesses de Python et C ++. Vous avez appris certaines des fonctionnalités de chaque langue et leur similitude.

Vous avez vu que C ++ est génial quand vous voulez:

  • Vitesse d'exécution rapide (potentiellement au détriment de la vitesse de développement)

  • Contrôle complet de la mémoire

Inversement, Python est idéal lorsque vous voulez:

  • Vitesse de développement rapide (potentiellement au détriment de la vitesse d'exécution)

  • Mémoire gérée

Vous êtes maintenant prêt à faire un choix judicieux de langue lors de votre prochain projet!