82 votes

Comportement contre-intuitif de int () en python

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

 int(1.23)
1
 

et int (chaîne) renvoie un entier 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 spéciale à cela? Je trouve contre-intuitif que la fonction soit dans un cas, mais pas dans l'autre.

123voto

holdenweb Points 3632

Il n'est pas spécial à la raison. Python est tout simplement de l'application de son principe général de ne pas effectuer les conversions implicites, qui sont des causes bien connues de problèmes, notamment pour les nouveaux arrivants, dans des langages tels que Perl et Javascript.

int(some_string) est une demande explicite de convertir une chaîne de format de nombre entier; les règles de conversion de préciser que la chaîne doit contenir un entier valide représentation littérale. int(float) est une demande explicite de convertir un float pour un entier; les règles de conversion de préciser que le flotteur de la partie fractionnaire sera tronqué.

Pour int("3.1459") de revenir 3 l'interprète aurait pour convertir implicitement la chaîne à un flotteur. Depuis le Python ne prend pas en charge les conversions implicites, il choisit de déclencher une exception à la place.

75voto

lvc Points 12046

Ce n'est presque certainement un cas de l'application de trois principes du Zen de Python:

Explicite est mieux implicite.

[...] la praticité beats pureté

Les erreurs ne doivent jamais passer sous silence

Un certain pourcentage de l'époque, quelqu'un qui fait int('1.23') appelle la mauvaise conversion de leurs cas d'utilisation, et veut quelque chose comme float ou decimal.Decimal à la place. Dans ces cas, il est clairement préférable pour eux d'obtenir immédiatement une erreur qu'ils puissent les réparer, plutôt que d'offrir silencieusement la valeur faux.

Dans le cas que vous ne souhaitez tronquer que pour un int, il est trivial explicitement de le faire en passant par float d'abord, puis en appelant l'un de l' int, round, trunc, floor ou ceil selon le cas. Cela rend votre code plus l'auto-documentation, la protection contre une modification ultérieure de "corriger" un hypothétique silencieusement tronquer int appel à l' float , en indiquant clairement que l'arrondi de la valeur est ce que vous voulez.

17voto

jamesdlin Points 13455

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

  • Le comportement d'Un: int('1.23') échoue avec une erreur. C'est le comportement existant.
  • Le comportement de B: int('1.23') produit 1 sans erreur. C'est ce que vous proposez.

Avec Un comportement, il est simple et trivial pour obtenir l'effet de comportement B: int(float('1.23')) à la place.

D'autre part, avec un comportement B, l'obtention de l'effet du comportement de l'Un 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 n'ai pas une totale confiance qu'il n'y a pas un coin de cas qu'il traite mal.)

Le comportement d'Un, par conséquent, est plus expressif que le comportement de B.

Une autre chose à considérer: '1.23' est une représentation de chaîne de valeur à virgule flottante. Convertir '1.23' pour un entier sur le plan conceptuel implique deux conversions (chaîne de flotter en entier), mais int(1.23) et int('1') chaque impliquer une seule conversion.


Edit:

Et en effet, il existe des cas limites que le code ci-dessus ne serait pas de poignée: 1e-2 et 1E-2 sont à la fois des valeurs à virgule flottante.

11voto

Timo Points 49

Dans des mots simples - ils ne sont pas la même fonction. int (décimal) et int (string) sont 2 fonctions différentes portant le même nom qui retournent un entier.

L’un est une nombre entier-conversion de chaînes, on effectue étage sur un nombre décimal, et ils sont appelés tous deux « int » parce qu’il est court et fait sens pour chacun, mais il n’y a aucune implication, ils sont accordent le même ou combiné fonctionnalités

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X