Recherche…


Introduction

Contrairement à la plupart des langages, Python prend en charge deux versions principales. Depuis 2008, quand Python 3 est sorti, beaucoup ont fait la transition, alors que beaucoup ne l'ont pas fait. Afin de comprendre les deux, cette section couvre les différences importantes entre Python 2 et Python 3.

Remarques

Il existe actuellement deux versions prises en charge de Python: 2.7 (Python 2) et 3.6 (Python 3). De plus, les versions 3.3 et 3.4 reçoivent les mises à jour de sécurité au format source.

Python 2.7 est rétrocompatible avec la plupart des versions antérieures de Python et peut exécuter le code Python de la plupart des versions 1.x et 2.x de Python sans modification. Il est largement disponible, avec une vaste collection de paquets. Il est également considéré comme obsolète par les développeurs de CPython et ne reçoit que le développement de la sécurité et des correctifs. Les développeurs de CPython ont l’intention d’abandonner cette version du langage en 2020 .

Selon Python Enhancement Proposal 373, il n'y aura pas de versions futures planifiées de Python 2 après le 25 juin 2016, mais les corrections de bogues et les mises à jour de sécurité seront prises en charge jusqu'en 2020 (il ne spécifie pas la date exacte de 2020). 2.)

Python 3 a intentionnellement rompu la compatibilité avec les versions antérieures pour répondre aux préoccupations des développeurs de langage concernant le noyau du langage. Python 3 reçoit de nouveaux développements et de nouvelles fonctionnalités. C'est la version du langage que les développeurs de langue ont l'intention de faire évoluer.

Au fil du temps, entre la version initiale de Python 3.0 et la version actuelle, certaines fonctionnalités de Python 3 ont été transférées dans Python 2.6, et d'autres parties de Python 3 ont été étendues pour avoir une syntaxe compatible avec Python 2. Il est donc possible d'écrire Python qui fonctionnera sur Python 2 et Python 3, en utilisant les futures importations et les modules spéciaux (comme six ).

Les futures importations doivent être au début de votre module:

from __future__ import print_function
# other imports and instructions go after __future__
print('Hello world')

Pour plus d'informations sur le module __future__ , consultez la page correspondante dans la documentation Python .

L' outil 2to3 est un programme Python qui convertit le code Python 2.x en code Python 3.x. Voir aussi la documentation Python .

Le paquet six fournit des utilitaires pour la compatibilité avec Python 2/3:

  • accès unifié aux bibliothèques renommées
  • variables pour les types chaîne / unicode
  • fonctions pour la méthode qui a été supprimée ou a été renommée

Une référence pour les différences entre Python 2 et Python 3 peut être trouvée ici .

Relevé d'impression ou fonction d'impression

Dans Python 2, print est une déclaration:

Python 2.x 2.7
print "Hello World"
print                         # print a newline
print "No newline",           # add trailing comma to remove newline 
print >>sys.stderr, "Error"   # print to stderr
print("hello")                # print "hello", since ("hello") == "hello"
print()                       # print an empty tuple "()"
print 1, 2, 3                 # print space-separated arguments: "1 2 3"
print(1, 2, 3)                # print tuple "(1, 2, 3)"

Dans Python 3, print() est une fonction, avec des arguments de mots-clés pour des utilisations courantes:

Python 3.x 3.0
print "Hello World"              # SyntaxError
print("Hello World")
print()                          # print a newline (must use parentheses)
print("No newline", end="")      # end specifies what to append (defaults to newline)
print("Error", file=sys.stderr)  # file specifies the output buffer
print("Comma", "separated", "output", sep=",")  # sep specifies the separator
print("A", "B", "C", sep="")     # null string for sep: prints as ABC
print("Flush this", flush=True)  # flush the output buffer, added in Python 3.3
print(1, 2, 3)                   # print space-separated arguments: "1 2 3"
print((1, 2, 3))                 # print tuple "(1, 2, 3)"

La fonction d'impression a les paramètres suivants:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

sep est ce qui sépare les objets que vous passez à imprimer. Par exemple:

print('foo', 'bar', sep='~') # out: foo~bar
print('foo', 'bar', sep='.') # out: foo.bar

end est la fin de l'instruction print. Par exemple:

print('foo', 'bar', end='!') # out: foo bar!

Impression à nouveau après une déclaration d'impression de fin de non-retour à la ligne imprimera à la même ligne:

print('foo', end='~')
print('bar')
# out: foo~bar

Remarque: Pour une compatibilité future, print fonction d’ print est également disponible dans Python 2.6 et supérieur . Cependant, il ne peut être utilisé que si l'analyse de l' instruction print est désactivée avec

from __future__ import print_function

Cette fonction a exactement le même format que celle de Python 3, sauf qu’elle ne contient pas le paramètre flush .

Voir PEP 3105 pour la justification.

Chaînes: Octets versus Unicode

Python 2.x 2.7

En Python 2, il existe deux variantes de chaîne: celles faites d’octets de type ( str ) et celles de texte de type ( unicode ).

Dans Python 2, un objet de type str est toujours une séquence d'octets, mais est couramment utilisé à la fois pour les données textuelles et binaires.

Un littéral de chaîne est interprété comme une chaîne d'octets.

s = 'Cafe'    # type(s) == str

Il y a deux exceptions: Vous pouvez définir un littéral Unicode (text) explicitement en préfixant le littéral avec u :

s = u'Café'   # type(s) == unicode
b = 'Lorem ipsum'  # type(b) == str

Vous pouvez également spécifier que les littéraux de chaîne d'un module entier doivent créer des littéraux Unicode (texte):

from __future__ import unicode_literals

s = 'Café'   # type(s) == unicode
b = 'Lorem ipsum'  # type(b) == unicode

Pour vérifier si votre variable est une chaîne (Unicode ou une chaîne d'octets), vous pouvez utiliser:

isinstance(s, basestring)
Python 3.x 3.0

Dans Python 3, le type str est un type de texte Unicode.

s = 'Cafe'           # type(s) == str
s = 'Café'           # type(s) == str (note the accented trailing e)

De plus, Python 3 a ajouté un objet bytes , adapté aux "blobs" binaires ou à l'écriture dans des fichiers indépendants du codage. Pour créer un objet octets, vous pouvez ajouter un préfixe b à un littéral de chaîne ou appeler la méthode d' encode la chaîne:

# Or, if you really need a byte string:
s = b'Cafe'          # type(s) == bytes
s = 'Café'.encode()  # type(s) == bytes

Pour tester si une valeur est une chaîne, utilisez:

isinstance(s, str)
Python 3.x 3.3

Il est également possible de préfixer des littéraux de chaîne avec un préfixe u pour faciliter la compatibilité entre les bases de code Python 2 et Python 3. Puisque, dans Python 3, toutes les chaînes sont Unicode par défaut, ajouter une chaîne à un littéral avec u n'a aucun effet:

u'Cafe' == 'Cafe'

Le préfixe de chaîne Unicode brut de Python 2, ur n'est pas supporté, cependant:

>>> ur'Café'
  File "<stdin>", line 1
    ur'Café'
           ^
SyntaxError: invalid syntax

Notez que vous devez encode un objet text ( str ) Python 3 pour le convertir en une représentation en bytes de ce texte. Le codage par défaut de cette méthode est UTF-8 .

Vous pouvez utiliser le decode pour demander à un objet bytes quel texte Unicode il représente:

>>> b.decode()
'Café'
Python 2.x 2.6

Bien que le type d' bytes existe à la fois dans Python 2 et 3, le type unicode n'existe que dans Python 2. Pour utiliser les chaînes Unicode implicites de Python 3 dans Python 2, ajoutez ce qui suit en haut de votre fichier de code:

from __future__ import unicode_literals
print(repr("hi"))
# u'hi'
Python 3.x 3.0

Une autre différence importante est que l’indexation des octets dans Python 3 donne un résultat int comme celui-ci:

b"abc"[0] == 97

Alors que le découpage en taille de 1 donne un objet de longueur 1 octet:

b"abc"[0:1] == b"a"

En outre, Python 3 corrige certains comportements inhabituels avec Unicode, à savoir l'inversion des chaînes d'octets dans Python 2. Par exemple, le problème suivant est résolu:

# -*- coding: utf8 -*-
print("Hi, my name is Łukasz Langa.")
print(u"Hi, my name is Łukasz Langa."[::-1])
print("Hi, my name is Łukasz Langa."[::-1])

# Output in Python 2
# Hi, my name is Łukasz Langa.
# .agnaL zsakuŁ si eman ym ,iH
# .agnaL zsaku�� si eman ym ,iH

# Output in Python 3
# Hi, my name is Łukasz Langa.
# .agnaL zsakuŁ si eman ym ,iH
# .agnaL zsakuŁ si eman ym ,iH

Division entière

Le symbole de division standard ( / ) fonctionne différemment dans Python 3 et Python 2 lorsqu'il est appliqué à des entiers.

Lors de la division d'un entier par un autre entier dans Python 3, l'opération de division x / y représente une division réelle (utilise la méthode __truediv__ ) et produit un résultat à virgule flottante. Pendant ce temps, la même opération dans Python 2 représente une division classique qui arrondit le résultat à l'infini négatif (également appelé prise de parole ).

Par exemple:

Code Sortie Python 2 Sortie Python 3
3 / 2 1 1,5
2 / 3 0 0.6666666666666666
-3 / 2 -2 -1.5

Le comportement d'arrondi par rapport à zéro a été déprécié dans Python 2.2 , mais reste dans Python 2.7 pour des raisons de compatibilité ascendante et a été supprimé dans Python 3.

Note: Pour obtenir un résultat flottant dans Python 2 (sans arrondi), vous pouvez spécifier l'un des opérandes avec le point décimal. L'exemple ci-dessus de 2/3 qui donne 0 dans Python 2 doit être utilisé comme 2 / 3.0 ou 2.0 / 3 ou 2.0/3.0 pour obtenir 0.6666666666666666

Code Sortie Python 2 Sortie Python 3
3.0 / 2.0 1,5 1,5
2 / 3.0 0.6666666666666666 0.6666666666666666
-3.0 / 2 -1.5 -1.5

Il y a aussi l' opérateur de division par étage ( // ), qui fonctionne de la même manière dans les deux versions: il est arrondi à l'entier le plus proche. (bien qu'un float soit retourné lorsqu'il est utilisé avec des floats) Dans les deux versions, l'opérateur // correspond à __floordiv__ .

Code Sortie Python 2 Sortie Python 3
3 // 2 1 1
2 // 3 0 0
-3 // 2 -2 -2
3.0 // 2.0 1.0 1.0
2.0 // 3 0.0 0.0
-3 // 2.0 -2,0 -2,0

On peut explicitement imposer une division réelle ou une division par étage en utilisant des fonctions natives dans le module operator :

from operator import truediv, floordiv
assert truediv(10, 8) == 1.25            # equivalent to `/` in Python 3
assert floordiv(10, 8) == 1              # equivalent to `//`

Bien que claire et explicite, l'utilisation des fonctions de l'opérateur pour chaque division peut être fastidieuse. La modification du comportement de l'opérateur / sera souvent préférée. Une pratique courante consiste à éliminer le comportement de division typique en ajoutant la from __future__ import division comme première instruction de chaque module:

# needs to be the first statement in a module
from __future__ import division
Code Sortie Python 2 Sortie Python 3
3 / 2 1,5 1,5
2 / 3 0.6666666666666666 0.6666666666666666
-3 / 2 -1.5 -1.5

from __future__ import division garantit que l'opérateur / représente la division vraie et uniquement dans les modules qui contiennent l'importation __future__ , il n'y a donc aucune raison impérieuse de ne pas l'activer dans tous les nouveaux modules.

Remarque : Certains autres langages de programmation arrondissent vers zéro (troncature) plutôt que vers l'infini négatif, contrairement à Python (dans ces langages -3 / 2 == -1 ). Ce comportement peut créer une confusion lors du portage ou de la comparaison du code.


Note sur les opérandes float : En alternative à la from __future__ import division , on pourrait utiliser le symbole de division habituel / et s'assurer qu'au moins un des opérandes est un float: 3 / 2.0 == 1.5 . Cependant, cela peut être considéré comme une mauvaise pratique. Il est trop facile d’écrire average = sum(items) / len(items) et oublier de lancer l’un des arguments pour flotter. De plus, de tels cas peuvent fréquemment échapper à la connaissance pendant le test, par exemple, si vous testez un tableau contenant des float mais recevez un tableau de données int en production. De plus, si le même code est utilisé dans Python 3, les programmes qui s'attendent à ce que 3 / 2 == 1 soit vrai ne fonctionneront pas correctement.

Voir PEP 238 pour une explication plus détaillée des raisons pour lesquelles l’opérateur de division a été modifié dans Python 3 et pourquoi l’ancienne division devrait être évitée.


Voir le sujet Mathématiques simples pour en savoir plus sur la division.

Réduire n'est plus un intégré

Dans Python 2, la reduce est disponible soit en tant que fonction intégrée, soit à partir du paquet functools (version 2.6 et functools ), tandis qu'en Python 3, la reduce n'est disponible qu'à partir de functools . Cependant, la syntaxe pour reduce à la fois dans Python2 et Python3 est identique et est reduce(function_to_reduce, list_to_reduce) .

Par exemple, considérons la réduction d'une liste à une valeur unique en divisant chacun des nombres adjacents. Ici, nous utilisons la fonction truediv de la bibliothèque d' operator .

Dans Python 2.x, c'est aussi simple que:

Python 2.x 2.3
>>> my_list = [1, 2, 3, 4, 5]
>>> import operator
>>> reduce(operator.truediv, my_list)
0.008333333333333333

Dans Python 3.x, l'exemple devient un peu plus compliqué:

Python 3.x 3.0
>>> my_list = [1, 2, 3, 4, 5]
>>> import operator, functools
>>> functools.reduce(operator.truediv, my_list)
0.008333333333333333

Nous pouvons également utiliser à from functools import reduce pour éviter d’appeler reduce avec le nom de l’espace de noms.

Différences entre les fonctions range et xrange

Dans Python 2, la fonction range renvoie une liste, tandis que xrange crée un objet xrange spécial, qui est une séquence immuable, qui, contrairement à d'autres types de séquence intégrés, ne prend pas en charge les méthodes d' index ni de count :

Python 2.x 2.3
print(range(1, 10))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

print(isinstance(range(1, 10), list))
# Out: True

print(xrange(1, 10))
# Out: xrange(1, 10)

print(isinstance(xrange(1, 10), xrange))
# Out: True

En Python 3, xrange a été étendu à la range séquence, ce qui crée ainsi maintenant une range objet. Il n'y a pas de type de xrange :

Python 3.x 3.0
print(range(1, 10))
# Out: range(1, 10)

print(isinstance(range(1, 10), range))
# Out: True

# print(xrange(1, 10))
# The output will be:
#Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#NameError: name 'xrange' is not defined

De plus, depuis Python 3.2, la range prend également en charge le découpage, l’ index et le count :

print(range(1, 10)[3:7])
# Out: range(3, 7)
print(range(1, 10).count(5))
# Out: 1
print(range(1, 10).index(7))
# Out: 6

L'avantage d'utiliser un type de séquence spécial au lieu d'une liste est que l'interpréteur n'a pas besoin d'allouer de la mémoire pour une liste et de la remplir:

Python 2.x 2.3
# range(10000000000000000)
# The output would be:
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# MemoryError

print(xrange(100000000000000000))
# Out: xrange(100000000000000000)

Comme ce dernier comportement est généralement souhaité, le premier a été supprimé dans Python 3. Si vous voulez toujours avoir une liste dans Python 3, vous pouvez simplement utiliser le constructeur list() sur un objet de range :

Python 3.x 3.0
print(list(range(1, 10)))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Compatibilité

Afin de maintenir la compatibilité entre les deux versions 2.x Python et Python 3.x, vous pouvez utiliser le builtins module du package externe future pour atteindre à la fois en avant et en arrière-compatiblité-compatiblité:

Python 2.x 2.0
#forward-compatible
from builtins import range

for i in range(10**8):
    pass
Python 3.x 3.0
#backward-compatible
from past.builtins import xrange

for i in xrange(10**8):
    pass

La range de la future bibliothèque prend en charge le découpage, l' index et le count dans toutes les versions de Python, tout comme la méthode intégrée sur Python 3.2+.

Déballer les Iterables

Python 3.x 3.0

Dans Python 3, vous pouvez décompresser une itération sans connaître le nombre exact d'éléments, et même avoir une variable contenant la fin de l'itérable. Pour cela, vous fournissez une variable pouvant collecter une liste de valeurs. Cela se fait en plaçant un astérisque avant le nom. Par exemple, décompresser une list :

first, second, *tail, last = [1, 2, 3, 4, 5]
print(first)
# Out: 1
print(second)
# Out: 2
print(tail)
# Out: [3, 4]
print(last)
# Out: 5

Remarque : Lorsque vous utilisez la syntaxe de la *variable , la variable sera toujours une liste, même si le type d’origine n’était pas une liste. Il peut contenir zéro ou plusieurs éléments en fonction du nombre d'éléments de la liste d'origine.

first, second, *tail, last = [1, 2, 3, 4]
print(tail)
# Out: [3]

first, second, *tail, last = [1, 2, 3]
print(tail)
# Out: []
print(last)
# Out: 3

De même, décompresser un str :

begin, *tail = "Hello"
print(begin)
# Out: 'H'
print(tail)
# Out: ['e', 'l', 'l', 'o']

Exemple de déballage d'une date ; _ est utilisé dans cet exemple comme une variable jetable (nous nous intéressons uniquement à la valeur de l' year ):

person = ('John', 'Doe', (10, 16, 2016))
*_, (*_, year_of_birth) = person
print(year_of_birth)
# Out: 2016

Il convient de mentionner que, puisque * mange un nombre variable d’éléments, vous ne pouvez pas avoir deux * pour la même itération dans une affectation - il ne saurait pas combien d’éléments entrent dans la première décompression, et combien dans la seconde. :

*head, *tail = [1, 2]
# Out: SyntaxError: two starred expressions in assignment
Python 3.x 3.5

Jusqu'à présent, nous avons discuté du déballage dans les missions. * et ** ont été étendus dans Python 3.5 . Il est maintenant possible d'avoir plusieurs opérations de décompression dans une expression:

{*range(4), 4, *(5, 6, 7)}
# Out: {0, 1, 2, 3, 4, 5, 6, 7}
Python 2.x 2.0

Il est également possible de décompresser une itération en arguments de fonction:

iterable = [1, 2, 3, 4, 5]
print(iterable)
# Out: [1, 2, 3, 4, 5]
print(*iterable)
# Out: 1 2 3 4 5
Python 3.x 3.5

Le déballage d'un dictionnaire utilise deux étoiles adjacentes ** ( PEP 448 ):

tail = {'y': 2, 'z': 3}
{'x': 1, **tail}
 # Out: {'x': 1, 'y': 2, 'z': 3}

Cela permet à la fois de remplacer les anciennes valeurs et de fusionner les dictionnaires.

dict1 = {'x': 1, 'y': 1}
dict2 = {'y': 2, 'z': 3}
{**dict1, **dict2}
# Out: {'x': 1, 'y': 2, 'z': 3}
Python 3.x 3.0

Python 3 a supprimé le déballage des tuple dans les fonctions. Par conséquent, ce qui suit ne fonctionne pas en Python 3

# Works in Python 2, but syntax error in Python 3:
map(lambda (x, y): x + y, zip(range(5), range(5)))
# Same is true for non-lambdas:
def example((x, y)):
    pass

# Works in both Python 2 and Python 3:
map(lambda x: x[0] + x[1], zip(range(5), range(5)))
# And non-lambdas, too:
def working_example(x_y):
    x, y = x_y
    pass

Voir PEP 3113 pour une justification détaillée.

Relever et gérer les exceptions

Voici la syntaxe Python 2, notez les virgules , sur les lignes raise et except :

Python 2.x 2.3
try:
    raise IOError, "input/output error"
except IOError, exc:
    print exc

En Python 3, la , la syntaxe est supprimée et remplacée par des parenthèses et as mot - clé:

try:
    raise IOError("input/output error")
except IOError as exc:
    print(exc)

Pour assurer la compatibilité avec les versions antérieures, la syntaxe Python 3 est également disponible dans Python 2.6 et doit donc être utilisée pour tout nouveau code qui ne doit pas nécessairement être compatible avec les versions précédentes.


Python 3.x 3.0

Python 3 ajoute également le chaînage des exceptions , dans lequel vous pouvez signaler qu'une autre exception est à l' origine de cette exception. Par exemple

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}') from e

L'exception déclenchée dans l'instruction except est de type DatabaseError , mais l'exception d'origine est marquée comme attribut __cause__ de cette exception. Lorsque la traceback est affichée, l'exception d'origine sera également affichée dans la traceback:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

Si vous lancez un bloc except sans chaînage explicite:

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}')

La traceback est

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')
Python 2.x 2.0

Ni l'un ni l'autre n'est pris en charge dans Python 2.x; l'exception d'origine et sa traceback seront perdues si une autre exception est déclenchée dans le bloc sauf. Le code suivant peut être utilisé pour la compatibilité:

import sys
import traceback

try:
    funcWithError()
except:
    sys_vers = getattr(sys, 'version_info', (0,))
    if sys_vers < (3, 0):
        traceback.print_exc()
    raise Exception("new exception")
Python 3.x 3.3

Pour "oublier" l'exception précédemment levée, utilisez raise from None

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}') from None

Maintenant, le traceur serait simplement

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

Ou pour le rendre compatible avec Python 2 et 3, vous pouvez utiliser les six paquets comme suit:

import six
try:
    file = open('database.db')
except FileNotFoundError as e:
    six.raise_from(DatabaseError('Cannot open {}'), None)

Méthode .next () sur les itérateurs renommés

Dans Python 2, un itérateur peut être parcouru en utilisant une méthode appelée next sur l'itérateur lui-même:

Python 2.x 2.3
g = (i for i in range(0, 3))
g.next()  # Yields 0
g.next()  # Yields 1
g.next()  # Yields 2

Dans Python 3, la méthode .next a été renommée en .__next__ , reconnaissant son rôle «magic», l'appel de .next déclenchera donc une .next AttributeError . La manière correcte d’accéder à cette fonctionnalité dans Python 2 et Python 3 consiste à appeler la fonction next avec l’itérateur comme argument.

Python 3.x 3.0
g = (i for i in range(0, 3))
next(g)  # Yields 0
next(g)  # Yields 1
next(g)  # Yields 2

Ce code est portable entre les versions 2.6 et actuelles.

Comparaison de différents types

Python 2.x 2.3

Des objets de différents types peuvent être comparés. Les résultats sont arbitraires mais cohérents. Ils sont classés de manière à ce que None soit inférieur à tout, les types numériques sont plus petits que les types non numériques et tout le reste est ordonné par type lexicographiquement. Ainsi, un int est inférieur à un str et un tuple est supérieur à une list :

[1, 2] > 'foo'
# Out: False
(1, 2) > 'foo'
# Out: True
[1, 2] > (1, 2)
# Out: False
100 < [1, 'x'] < 'xyz' < (1, 'x')
# Out: True

Cela a été fait à l'origine afin qu'une liste de types mixtes puisse être triée et que les objets soient regroupés par type:

l = [7, 'x', (1, 2), [5, 6], 5, 8.0, 'y', 1.2, [7, 8], 'z']
sorted(l)
# Out: [1.2, 5, 7, 8.0, [5, 6], [7, 8], 'x', 'y', 'z', (1, 2)]
Python 3.x 3.0

Une exception est déclenchée lors de la comparaison de différents types (non numériques):

1 < 1.5
# Out: True

[1, 2] > 'foo'
# TypeError: unorderable types: list() > str()
(1, 2) > 'foo'
# TypeError: unorderable types: tuple() > str()
[1, 2] > (1, 2)
# TypeError: unorderable types: list() > tuple()

Pour trier les listes mixtes dans Python 3 par types et pour assurer la compatibilité entre les versions, vous devez fournir une clé pour la fonction triée:

>>> list = [1, 'hello', [3, 4], {'python': 2}, 'stackoverflow', 8, {'python': 3}, [5, 6]]
>>> sorted(list, key=str)
# Out: [1, 8, [3, 4], [5, 6], 'hello', 'stackoverflow', {'python': 2}, {'python': 3}]

L'utilisation de str comme fonction key convertit temporairement chaque élément en chaîne uniquement à des fins de comparaison. Il voit ensuite la représentation des chaînes commençant par [ , ' , { ou 0-9 et il est capable de les trier (et tous les caractères suivants).

Entrée utilisateur

En Python 2, les entrées utilisateur sont acceptées en utilisant la fonction raw_input ,

Python 2.x 2.3
user_input = raw_input()

En Python 3, l'entrée utilisateur est acceptée à l'aide de la fonction d' input .

Python 3.x 3.0
user_input = input()

En Python 2, l' input fonction accepte l' entrée et l' interpréter. Bien que cela puisse être utile, il a plusieurs considérations de sécurité et a été supprimé dans Python 3. Pour accéder à la même fonctionnalité, eval(input()) peut être utilisé.

Pour garder un script portable entre les deux versions, vous pouvez placer le code ci-dessous en haut de votre script Python:

try:
    input = raw_input
except NameError:
    pass

Changement de méthode de dictionnaire

Dans Python 3, de nombreuses méthodes de dictionnaire ont un comportement très différent de celui de Python 2, et beaucoup ont été supprimées également: has_key , iter* et view* ont disparu. Au lieu de d.has_key(key) , longtemps obsolète, il faut maintenant utiliser key in d .

Dans Python 2, les keys méthodes de dictionnaire, les values et les items renvoient des listes. Dans Python 3, ils renvoient des objets de vue à la place; les objets de vue ne sont pas des itérateurs et ils en diffèrent de deux manières, à savoir:

  • ils ont la taille (on peut utiliser la fonction len sur eux)
  • ils peuvent être répétés plusieurs fois

De plus, comme avec les itérateurs, les modifications apportées au dictionnaire sont reflétées dans les objets de vue.

Python 2.7 a rétrogradé ces méthodes depuis Python 3; Ils sont disponibles sous viewkeys de viewkeys , de viewvalues et de viewitems . Pour transformer le code Python 2 en code Python 3, les formulaires correspondants sont les suivants:

  • d.keys() , d.values() et d.items() de Python 2 doivent être remplacés par list(d.keys()) , list(d.values()) et list(d.items())
  • d.iterkeys() , d.itervalues() et d.iteritems() doivent être changés en iter(d.keys()) , ou même mieux, iter(d) ; iter(d.values()) et iter(d.items()) respectivement
  • et enfin les méthodes d.viewkeys() , d.viewvalues() et d.viewitems() peuvent être remplacées par d.keys() , d.values() et d.items() .

Le portage du code Python 2 qui itère sur les clés, les valeurs ou les éléments du dictionnaire tout en le mutant est parfois délicat. Considérer:

d = {'a': 0, 'b': 1, 'c': 2, '!': 3}
for key in d.keys():
    if key.isalpha():
        del d[key]

Le code semble fonctionner de la même manière dans Python 3, mais la méthode keys renvoie un objet de vue, pas une liste, et si le dictionnaire change de taille en itération, le code Python 3 se bloquera avec RuntimeError: dictionary changed size during iteration . La solution est bien sûr d'écrire correctement for key in list(d) .

De même, les objets de vue se comportent différemment des itérateurs: on ne peut pas utiliser next() et on ne peut pas reprendre l' itération; au lieu de cela redémarrer; Si le code Python 2 transmet la valeur de retour de d.iterkeys() , d.itervalues() ou d.iteritems() à une méthode qui attend un itérateur au lieu d'une itération , cela devrait être iter(d) , iter(d.values()) ou iter(d.items()) dans Python 3.

instruction exec est une fonction dans Python 3

Dans Python 2, exec est une instruction, avec une syntaxe spéciale: exec code [in globals[, locals]]. Dans Python 3, exec est maintenant une fonction: exec(code, [, globals[, locals]]) , et la syntaxe Python 2 SyntaxError une SyntaxError .

Au fur et à mesure que print passait d'une instruction à une fonction, une importation __future__ était également ajoutée. Cependant, il n'y a pas from __future__ import exec_function , car il n'est pas nécessaire: l'instruction exec dans Python 2 peut également être utilisée avec une syntaxe qui ressemble exactement à l' exec fonction exec dans Python 3. Vous pouvez donc modifier les instructions

Python 2.x 2.3
exec 'code'
exec 'code' in global_vars
exec 'code' in global_vars, local_vars

aux formes

Python 3.x 3.0
exec('code')
exec('code', global_vars)
exec('code', global_vars, local_vars)

et ces dernières formes sont garanties de fonctionner de manière identique dans Python 2 et Python 3.

bug de la fonction hasattr dans Python 2

Dans Python 2, lorsqu'une propriété hasattr une erreur, hasattr ignore cette propriété et renvoie False .

class A(object):
    @property
    def get(self):
        raise IOError


class B(object):
    @property
    def get(self):
        return 'get in b'

a = A()
b = B()

print 'a hasattr get: ', hasattr(a, 'get')
# output False in Python 2 (fixed, True in Python 3)
print 'b hasattr get', hasattr(b, 'get')
# output True in Python 2 and Python 3

Ce bug est corrigé dans Python3. Donc, si vous utilisez Python 2, utilisez

try:
    a.get
except AttributeError:
    print("no get property!")

ou utilisez plutôt getattr

p = getattr(a, "get", None)
if p is not None:
    print(p)
else:
    print("no get property!")

Modules renommés

Quelques modules de la bibliothèque standard ont été renommés:

Ancien nom Nouveau nom
_winreg winreg
ConfigParser configparser
copy_reg copyreg
Queue queue
SocketServer socketserver
_markupbase markupbase
repr reproche
test.test_support test.support
Tkinter tkinter
tkFileDialog tkinter.filedialog
urllib / urllib2 urllib, urllib.parse, urllib.error, urllib.response, urllib.request, urllib.robotparser

Certains modules ont même été convertis de fichiers en bibliothèques. Prenons l'exemple de tkinter et urllib ci-dessus.

Compatibilité

Lorsque vous maintenez la compatibilité entre les versions Python 2.x et 3.x, vous pouvez utiliser le future package externe pour importer des packages de bibliothèque standard de niveau supérieur avec des noms Python 3.x sur les versions Python 2.x.

Constantes Octales

Dans Python 2, un littéral octal pourrait être défini comme

>>> 0755  # only Python 2

Pour assurer la compatibilité croisée, utilisez

0o755  # both Python 2 and Python 3

Toutes les classes sont des "nouvelles classes" dans Python 3.

Dans Python 3.x toutes les classes sont des classes de nouveau style ; lors de la définition d'une nouvelle classe, python le fait hériter implicitement de l' object . En tant que tel, la spécification d’un object dans une définition de class est une option complètement facultative:

Python 3.x 3.0
class X: pass
class Y(object): pass

Ces deux classes contiennent désormais des object dans leur mro (ordre de résolution de la méthode):

Python 3.x 3.0
>>> X.__mro__
(__main__.X, object)

>>> Y.__mro__
(__main__.Y, object)

Dans Python 2.x classes sont, par défaut, d'anciennes classes; ils n'héritent pas implicitement d' object . Cela fait que la sémantique des classes diffère selon que l'on ajoute explicitement un object tant que class base:

Python 2.x 2.3
class X: pass
class Y(object): pass

Dans ce cas, si nous essayons d'imprimer le __mro__ de Y , une sortie similaire à celle du cas Python 3.x apparaîtra:

Python 2.x 2.3
>>> Y.__mro__
(<class '__main__.Y'>, <type 'object'>)

Cela se produit parce que nous avons explicitement fait hériter Y de l’objet lors de sa définition: class Y(object): pass . Pour la classe X qui n'hérite pas d'objet, l'attribut __mro__ n'existe pas, en essayant d'y accéder aboutit à une erreur AttributeError .

Afin de garantir la compatibilité entre les deux versions de Python, les classes peuvent être définies avec un object comme classe de base:

class mycls(object):
    """I am fully compatible with Python 2/3"""

Alternativement, si la variable __metaclass__ est définie pour type une portée globale, toutes les classes définies ultérieurement dans un module donné sont implicitement new-style sans avoir à hériter explicitement de l' object :

__metaclass__ = type

class mycls:
    """I am also fully compatible with Python 2/3"""

Suppression des opérateurs <> et ``, synonyme de! = Et repr ()

Dans Python 2, <> est un synonyme de != ; de même, `foo` est un synonyme de repr(foo) .

Python 2.x 2.7
>>> 1 <> 2
True
>>> 1 <> 1
False
>>> foo = 'hello world'
>>> repr(foo)
"'hello world'"
>>> `foo`
"'hello world'"
Python 3.x 3.0
>>> 1 <> 2
  File "<stdin>", line 1
    1 <> 2
       ^
SyntaxError: invalid syntax
>>> `foo`
  File "<stdin>", line 1
    `foo`
    ^
SyntaxError: invalid syntax

encoder / décoder en hexadécimal n'est plus disponible

Python 2.x 2.7
"1deadbeef3".decode('hex')
# Out: '\x1d\xea\xdb\xee\xf3'
'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Out: 1deadbeef3
Python 3.x 3.0
"1deadbeef3".decode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# AttributeError: 'str' object has no attribute 'decode'

b"1deadbeef3".decode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# LookupError: 'hex' is not a text encoding; use codecs.decode() to handle arbitrary codecs

'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs

b'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# AttributeError: 'bytes' object has no attribute 'encode'

Cependant, comme suggéré par le message d'erreur, vous pouvez utiliser le module de codecs pour obtenir le même résultat:

import codecs
codecs.decode('1deadbeef4', 'hex')
# Out: b'\x1d\xea\xdb\xee\xf4'
codecs.encode(b'\x1d\xea\xdb\xee\xf4', 'hex')
# Out: b'1deadbeef4'

Notez que codecs.encode renvoie un objet bytes . Pour obtenir un objet str , il suffit de decode en ASCII:

codecs.encode(b'\x1d\xea\xdb\xee\xff', 'hex').decode('ascii')
# Out: '1deadbeeff'

Fonction cmp supprimée dans Python 3

Dans Python 3, la fonction intégrée cmp été supprimée, avec la méthode spéciale __cmp__ .

De la documentation:

La fonction cmp() doit être considérée comme disparue et la méthode spéciale __cmp__() n'est plus prise en charge. Utilisez __lt__() pour le tri, __eq__() avec __hash__() , et d'autres comparaisons riches si nécessaire. (Si vous avez vraiment besoin de la fonctionnalité cmp() , vous pouvez utiliser l'expression (a > b) - (a < b) comme équivalent pour cmp(a, b) .)

De plus, toutes les fonctions intégrées acceptant le paramètre cmp acceptent désormais uniquement le paramètre key mot clé uniquement.

Dans le module functools il y a aussi une fonction utile cmp_to_key(func) qui vous permet de convertir une fonction de style cmp une fonction de style key :

Transformer une ancienne fonction de comparaison en une fonction clé. Utilisé avec les outils qui acceptent les fonctions clés (telles que sorted() , min() , max() , heapq.nlargest() , heapq.nsmallest() , itertools.groupby() ). Cette fonction est principalement utilisée comme outil de transition pour les programmes en cours de conversion à partir de Python 2 qui prend en charge l’utilisation de fonctions de comparaison.

Variables fuites dans la compréhension de la liste

Python 2.x 2.3
x = 'hello world!'
vowels = [x for x in 'AEIOU'] 

print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'U'   
Python 3.x 3.0
x = 'hello world!'
vowels = [x for x in 'AEIOU']

print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'hello world!'

Comme on peut le voir sur l'exemple, dans Python 2, la valeur de x été divulguée: cela masquait hello world! et imprimé U , puisque c'était la dernière valeur de x à la fin de la boucle.

Cependant, en Python 3 x imprime le monde original défini à l'origine hello world! , puisque la variable locale de la compréhension de la liste ne masque pas les variables de la portée environnante.

De plus, ni les expressions génératrices (disponibles dans Python depuis la version 2.5), ni les interprétations de dictionnaire ou de jeu (qui ont été renvoyées vers Python 2.7 à partir de Python 3), ne contenaient de variables dans Python 2.

Notez que dans Python 2 et Python 3, les variables entrent dans la portée environnante lors de l'utilisation d'une boucle for:

x = 'hello world!'
vowels = []
for x in 'AEIOU':
    vowels.append(x)
print(x)
# Out: 'U'

carte()

map() est une méthode intégrée utile pour appliquer une fonction aux éléments d'une itération. Dans Python 2, map renvoie une liste. Dans Python 3, map renvoie un objet map , qui est un générateur.

# Python 2.X
>>> map(str, [1, 2, 3, 4, 5])
['1', '2', '3', '4', '5']
>>> type(_)
>>> <class 'list'>

# Python 3.X
>>> map(str, [1, 2, 3, 4, 5])
<map object at 0x*>
>>> type(_)
<class 'map'>

# We need to apply map again because we "consumed" the previous map....
>>> map(str, [1, 2, 3, 4, 5])
>>> list(_)
['1', '2', '3', '4', '5']

Dans Python 2, vous pouvez transmettre None pour servir de fonction d'identité. Cela ne fonctionne plus dans Python 3.

Python 2.x 2.3
>>> map(None, [0, 1, 2, 3, 0, 4])
[0, 1, 2, 3, 0, 4]
Python 3.x 3.0
>>> list(map(None, [0, 1, 2, 3, 0, 5]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

De plus, lors du passage de plusieurs arguments itérables en tant que arguments dans Python 2, les plaquettes de map les itérables les plus courtes avec None (similaire à itertools.izip_longest ). Dans Python 3, l'itération s'arrête après la plus courte itération.

En Python 2:

Python 2.x 2.3
>>> map(None, [1, 2, 3], [1, 2], [1, 2, 3, 4, 5])
[(1, 1, 1), (2, 2, 2), (3, None, 3), (None, None, 4), (None, None, 5)]

En Python 3:

Python 3.x 3.0
>>> list(map(lambda x, y, z: (x, y, z), [1, 2, 3], [1, 2], [1, 2, 3, 4, 5]))
[(1, 1, 1), (2, 2, 2)]

# to obtain the same padding as in Python 2 use zip_longest from itertools
>>> import itertools
>>> list(itertools.zip_longest([1, 2, 3], [1, 2], [1, 2, 3, 4, 5]))
[(1, 1, 1), (2, 2, 2), (3, None, 3), (None, None, 4), (None, None, 5)]

Note : au lieu de map utilisez des listes compréhensibles compatibles avec Python 2/3. Remplacement de la map(str, [1, 2, 3, 4, 5]) :

>>> [str(i) for i in [1, 2, 3, 4, 5]]
['1', '2', '3', '4', '5']

filter (), map () et zip () renvoient des itérateurs au lieu de séquences

Python 2.x 2.7

Dans le filter Python 2, les fonctions intégrées map et zip renvoient une séquence. map et zip renvoient toujours une liste alors qu'avec filter le type de retour dépend du type de paramètre donné:

>>> s = filter(lambda x: x.isalpha(), 'a1b2c3')
>>> s
'abc'
>>> s = map(lambda x: x * x, [0, 1, 2])
>>> s
[0, 1, 4]
>>> s = zip([0, 1, 2], [3, 4, 5])
>>> s
[(0, 3), (1, 4), (2, 5)]
Python 3.x 3.0

Dans Python 3 filter , map et zip return iterator à la place:

>>> it = filter(lambda x: x.isalpha(), 'a1b2c3')
>>> it
<filter object at 0x00000098A55C2518>
>>> ''.join(it)
'abc'
>>> it = map(lambda x: x * x, [0, 1, 2])
>>> it
<map object at 0x000000E0763C2D30>
>>> list(it)
[0, 1, 4]
>>> it = zip([0, 1, 2], [3, 4, 5])
>>> it
<zip object at 0x000000E0763C52C8>
>>> list(it)
[(0, 3), (1, 4), (2, 5)]

Puisque Python 2 itertools.izip est équivalent à Python 3, zip izip a été supprimé sur Python 3.

Importations absolues / relatives

Dans Python 3, PEP 404 modifie la façon dont les importations fonctionnent à partir de Python 2. Les importations relatives implicites ne sont plus autorisées dans les packages et à from ... import * importations ne sont autorisées que dans le code de niveau module.

Pour obtenir le comportement de Python 3 dans Python 2:

  • la fonctionnalité d' importation absolue peut être activée à from __future__ import absolute_import
  • les importations relatives explicites sont encouragées à la place des importations implicites relatives

Pour plus de clarté, dans Python 2, un module peut importer le contenu d'un autre module situé dans le même répertoire, comme suit:

import foo

Notez que l'emplacement de foo est ambigu à partir de la seule déclaration d'importation. Ce type d'importation implicite relative est donc déconseillé en faveur d' importations relatives explicites , qui ressemblent à ce qui suit:

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
from ...package import bar
from ...sys import path

Le point . permet une déclaration explicite de l'emplacement du module dans l'arborescence.


Plus sur les importations relatives

Considérons un paquet défini par l'utilisateur appelé shapes . La structure du répertoire est la suivante:

shapes
├── __init__.py
|
├── circle.py
|
├── square.py
|
└── triangle.py

circle.py , square.py et triangle.py importent tous util.py tant que module. Comment vont-ils se référer à un module du même niveau?

 from . import util # use util.PI, util.sq(x), etc

OU

 from .util import * #use PI, sq(x), etc to call functions

Le . est utilisé pour les importations relatives de même niveau.

Considérons maintenant une autre disposition du module de shapes :

shapes
├── __init__.py
|
├── circle
│   ├── __init__.py
│   └── circle.py
|
├── square
│   ├── __init__.py
│   └── square.py
|
├── triangle
│   ├── __init__.py
│   ├── triangle.py
|
└── util.py

Maintenant, comment ces 3 classes se réfèrent-elles à util.py?

 from .. import util # use util.PI, util.sq(x), etc

OU

 from ..util import * # use PI, sq(x), etc to call functions

Le .. est utilisé pour les importations relatives au niveau parent. Ajouter plus . s avec nombre de niveaux entre le parent et l'enfant.

Fichier I / O

file n'est plus un nom intégré dans 3.x ( open works).

Les détails internes des E / S de fichiers ont été déplacés vers le module io standard de la bibliothèque, qui est également la nouvelle StringIO de StringIO :

import io
assert io.open is open # the builtin is an alias
buffer = io.StringIO()
buffer.write('hello, ') # returns number of characters written
buffer.write('world!\n')
buffer.getvalue() # 'hello, world!\n'

Le mode fichier (text vs binary) détermine maintenant le type de données produit en lisant un fichier (et le type requis pour l'écriture):

with open('data.txt') as f:
    first_line = next(f)
    assert type(first_line) is str
with open('data.bin', 'rb') as f:
    first_kb = f.read(1024)
    assert type(first_kb) is bytes

Le codage des fichiers texte est locale.getpreferredencoding(False) par défaut sur tout ce qui est renvoyé par locale.getpreferredencoding(False) . Pour spécifier explicitement un codage, utilisez le paramètre de mot-clé encoding :

with open('old_japanese_poetry.txt', 'shift_jis') as text:
    haiku = text.read()

La fonction round () et le type de retour

bris de cravate

En Python 2, l'utilisation de round() sur un nombre proche de deux nombres entiers renvoie la valeur la plus éloignée de 0. Par exemple:

Python 2.x 2.7
round(1.5)  # Out: 2.0
round(0.5)  # Out: 1.0
round(-0.5)  # Out: -1.0
round(-1.5)  # Out: -2.0

Dans Python 3 cependant, round() renverra l'entier pair ( l'arrondi des banquiers ). Par exemple:

Python 3.x 3.0
round(1.5)  # Out: 2
round(0.5)  # Out: 0
round(-0.5)  # Out: 0
round(-1.5)  # Out: -2

La fonction round () suit la stratégie d' arrondissement de moitié à pair qui arrondira les nombres à mi-chemin au nombre entier pair le plus proche (par exemple, round(2.5) renvoie désormais 2 plutôt que 3.0).

Selon la référence dans Wikipedia , ceci est également connu sous le nom d' arrondi sans biais, d'arrondi convergent, d'arrondi de statisticien, d'arrondissement hollandais, d'arrondi gaussien ou d' arrondi impair .

La moitié à l'arrondissement fait partie de la norme IEEE 754 et c'est aussi le mode d'arrondi par défaut dans Microsoft .NET.

Cette stratégie d'arrondissement tend à réduire l'erreur d'arrondi totale. Étant donné qu'en moyenne, le nombre de chiffres arrondis est le même que le nombre de chiffres arrondis, les erreurs d'arrondi sont annulées. D'autres méthodes d'arrondi ont plutôt tendance à avoir un biais à la hausse ou à la baisse dans l'erreur moyenne.


type de retour round ()

La fonction round() renvoie un type float dans Python 2.7

Python 2.x 2.7
round(4.8)
# 5.0

À partir de Python 3.0, si le second argument (nombre de chiffres) est omis, il renvoie un int .

Python 3.x 3.0
round(4.8)
# 5

Vrai, Faux et Aucun

Dans Python 2, True , False et None sont des constantes intégrées. Ce qui signifie qu'il est possible de les réaffecter.

Python 2.x 2.0
True, False = False, True
True   # False
False  # True

Vous ne pouvez pas faire cela avec None depuis Python 2.4.

Python 2.x 2.4
None = None  # SyntaxError: cannot assign to None

Dans Python 3, True , False et None sont maintenant des mots-clés.

Python 3.x 3.0
True, False = False, True  # SyntaxError: can't assign to keyword

None = None  # SyntaxError: can't assign to keyword

Renvoie la valeur lors de l'écriture dans un objet fichier

En Python 2, l'écriture directe dans un descripteur de fichier renvoie None :

Python 2.x 2.3
hi = sys.stdout.write('hello world\n')
# Out: hello world
type(hi)
# Out: <type 'NoneType'>

Dans Python 3, l’écriture dans un handle renvoie le nombre de caractères écrits lors de l’écriture du texte et le nombre d’octets écrits lors de l’écriture des octets:

Python 3.x 3.0
import sys

char_count = sys.stdout.write('hello world 🐍\n')
# Out: hello world 🐍
char_count
# Out: 14

byte_count = sys.stdout.buffer.write(b'hello world \xf0\x9f\x90\x8d\n')
# Out: hello world 🐍
byte_count
# Out: 17

long vs int

Dans Python 2, tout entier supérieur à C ssize_t serait converti en type de données long , indiqué par un suffixe L sur le littéral. Par exemple, sur une version 32 bits de Python:

Python 2.x 2.7
>>> 2**31
2147483648L
>>> type(2**31)
<type 'long'>
>>> 2**30
1073741824
>>> type(2**30)
<type 'int'>
>>> 2**31 - 1  # 2**31 is long and long - int is long
2147483647L

Cependant, dans Python 3, le type de données long été supprimé. peu importe la taille de l'entier, ce sera un int .

Python 3.x 3.0
2**1024
# Output: 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
print(-(2**1024))
# Output: -179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
type(2**1024)
# Output: <class 'int'>

Valeur booléenne de classe

Python 2.x 2.7

Dans Python 2, si vous souhaitez définir vous-même une valeur booléenne de classe, vous devez implémenter la méthode __nonzero__ dans votre classe. La valeur est True par défaut.

class MyClass:
    def __nonzero__(self):
        return False

my_instance = MyClass()
print bool(MyClass)       # True
print bool(my_instance)   # False
Python 3.x 3.0

En Python 3, __bool__ est utilisé à la place de __nonzero__

class MyClass:
    def __bool__(self):
        return False

my_instance = MyClass()
print(bool(MyClass))       # True
print(bool(my_instance))   # False


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow