Comportement contre-intuitif de int () en python

Il est clairement indiqué dans les documents que int (nombre) est une conversion de type plancher:

int(1.23) 1 

et int (ssortingng) renvoie un int si et seulement si la chaîne est un littéral entier.

 int('1.23') ValueError int('1') 1 

Y a-t-il une raison particulière à cela? Je trouve contre-intuitif que la fonction se déroule dans un cas, mais pas dans l’autre.

Il n’y a pas de raison particulière . Python applique simplement son principe général de ne pas effectuer de conversions implicites, qui sont des causes bien connues de problèmes, en particulier pour les nouveaux venus, dans des langages tels que Perl et Javascript.

int(some_ssortingng) est une requête explicite pour convertir une chaîne au format entier; les règles pour cette conversion spécifient que la chaîne doit contenir une représentation littérale de nombre entier valide. int(float) est une requête explicite pour convertir un float en un entier; les règles pour cette conversion spécifient que la partie fractionnaire du flottant sera tronquée.

Pour que int("3.1459") retourne 3 l’interpréteur devra convertir implicitement la chaîne en float. Comme Python ne prend pas en charge les conversions implicites, il choisit plutôt de générer une exception.

Il s’agit presque certainement d’appliquer trois des principes du Zen de Python :

Explicit est mieux implicite.

[…] pratique bat la pureté

Les erreurs ne doivent jamais passer silencieusement

Un certain pourcentage du temps, quelqu’un faisant int('1.23') appelle la mauvaise conversion pour son cas d’utilisation, et veut quelque chose comme float ou decimal.Decimal place. Dans ces cas, il est clairement préférable pour eux d’obtenir une erreur immédiate qu’ils peuvent corriger, plutôt que de donner silencieusement la mauvaise valeur.

Dans le cas où vous voulez tronquer cela en int, il est sortingvial de le faire explicitement en passant d’abord par float , puis en appelant l’un des éléments int , round , trunc , floor ou ceil selon le cas. Cela rend également votre code plus auto-documenté, évitant toute modification ultérieure “corrigeant” un appel intel hypothétique à tronquer en silence en indiquant clairement que la valeur arrondie est ce que vous voulez.

Parfois, une expérience de reflection peut être utile.

  • Comportement A: int('1.23') échoue avec une erreur. C’est le comportement existant.
  • Comportement B: int('1.23') produit 1 sans erreur. C’est ce que vous proposez.

Avec le comportement A, il est simple et sortingvial d’obtenir l’effet du comportement B: utilisez plutôt int(float('1.23')) .

Par contre, avec le comportement B, obtenir l’effet du comportement A est nettement plus compliqué:

 def parse_pure_int(s): if "." in s: raise ValueError("invalid literal for integer with base 10: " + s) return int(s) 

(et même avec le code ci-dessus, je ne suis pas certain qu’il n’y a pas de problème de coin).

Le comportement A est donc plus expressif que le comportement B.

Une autre chose à considérer: '1.23' est une représentation sous forme de chaîne d’une valeur à virgule flottante. La conversion conceptuelle de '1.23' en un entier implique deux conversions (chaîne à flotter en entier), mais int(1.23) et int('1') impliquent une seule conversion.


Modifier:

Et en effet, le code ci-dessus ne gère pas les cas particuliers: 1e-2 et 1E-2 sont également des valeurs à virgule flottante.

En termes simples – ce ne sont pas les mêmes fonctions.

  • int (décimal) se comporte comme ‘plancher c’est-à-dire assumr la partie décimale et retourner comme int’
  • int (chaîne) se comporte comme si ce texte décrit un entier, le convertit et le retourne en tant qu’int.

Ce sont 2 fonctions différentes avec le même nom qui renvoient un entier mais ce sont des fonctions différentes.

‘int’ est court et facile à retenir et sa signification appliquée à chaque type est intuitive pour la plupart des programmeurs, c’est pourquoi ils l’ont choisi.

Il n’y a aucune implication qu’ils fournissent les mêmes fonctionnalités ou des fonctionnalités combinées, ils ont simplement le même nom et renvoient le même type. Ils pourraient aussi bien s’appeler ‘floorDecimalAsInt’ et ‘convertSsortingngToInt’, mais ils sont allés à «int» car ils sont faciles à retenir (99%) intuitifs et la confusion est rare.

Analyser du texte en tant qu’Integer pour un texte comportant un point décimal tel que “4.5” provoquerait une erreur dans la majorité des langages informatiques et provoquerait une erreur chez la majorité des programmeurs, puisque la valeur text ne représente pas un entier et implique ils fournissent des données erronées