python中int()的违反直觉的行为

时间:2016-03-18 13:06:00

标签: python

docs中明确指出int(number)是地板类型转换:

int(1.23)
1
当且仅当字符串是整数文字时,

和int(string)才返回一个int。

int('1.23')
ValueError

int('1')
1

有什么特别原因吗?我发现在一种情况下功能下降而不是另一种情况是违反直觉的。

4 个答案:

答案 0 :(得分:124)

没有特殊原因。 Python只是应用其不执行隐式转换的一般原则,隐式转换是众所周知的问题原因,特别是对于新手,在Perl和Javascript等语言中。

int(some_string)是将字符串转换为整数格式的显式请求;此转换的规则指定该字符串必须包含有效的整数文字表示。 int(float)是将float转换为整数的显式请求;此转换的规则指定浮点数的小数部分将被截断。

为了让int("3.1459")返回3,解释器必须隐式地将字符串转换为float。由于Python不支持隐式转换,因此它选择引发异常。

答案 1 :(得分:76)

这几乎可以肯定是应用Zen of Python中的三个原则:

  

显式更好隐含。

     

[...]实用性胜过纯洁

     

错误不应该以无声方式传递

有些百分比的时间,有人int('1.23')正在为其用例调用错误的转化,并希望改为floatdecimal.Decimal。在这些情况下,他们明显更好地获得他们可以修复的即时错误,而不是默默地给出错误的值。

如果想要将其截断为int,那么首先通过float传递它然后调用{{1}中的一个来显式地这样做是微不足道的。适当时,},introundtruncfloor。这也使您的代码更加自我记录,防止以后的修改"纠正"通过明确指出舍入值您想要的内容,假设默默地截断ceilint的调用。

答案 2 :(得分:17)

有时思考实验会很有用。

  • 行为A:int('1.23')失败并显示错误。这是现有行为。
  • 行为B:int('1.23')生成1且没有错误。这就是你提出的建议。

通过行为A,可以直接轻松地获得行为B的效果:改为使用int(float('1.23'))

另一方面,对于行为B,获得行为A的效果要复杂得多:

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

(即使使用上面的代码,我也没有完全相信没有一些错误处理的错误案例。)

因此,行为A比行为B更具表现力。

要考虑的另一件事:'1.23'是浮点值的字符串表示。从概念上将'1.23'转换为整数涉及两次转换(字符串要浮动到整数),但int(1.23)int('1')每次只涉及一次转换。

编辑:

事实上,上面的代码无法处理:* {1}}和1e-2都是浮点值。

答案 3 :(得分:11)

简单来说 - 它们的功能不同。

  • int(decimal)表现为'floor,即敲掉小数部分并返回int'
  • int(string)表现为'此文本描述一个整数,将其转换并返回为int'。

它们是2个不同的函数,同名返回一个整数,但它们是不同的函数。

'int'简短且易于记忆,其适用于每种类型的含义对于大多数程序员来说都是直观的,这就是他们选择它的原因。

没有暗示它们提供相同或组合的功能,它们只是具有相同的名称并返回相同的类型。它们可以很容易地被称为'floorDecimalAsInt'和'convertStringToInt',但它们用于'int'因为它易于记忆,(99%)直观且很少发生混淆。

将文本解析为包含小数点(例如“4.5”)的文本的整数将在计算机语言的多数中引发错误,并且预计会通过多数抛出错误