Python 中 int()的反直觉行为

医生中明确指出,int (数字)是一种地板类型转换:

int(1.23)
1

Int (string)返回一个 int 当且仅当该字符串是一个整数文字。

int('1.23')
ValueError


int('1')
1

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

5305 次浏览

几乎可以肯定,这种情况适用了 巨蟒之禅的三项原则:

显式的更好。

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

错误永远不会悄无声息地过去

在某些百分比的情况下,执行 int('1.23')的某些人正在为他们的用例调用错误的转换,并希望使用类似于 floatdecimal.Decimal的转换。在这些情况下,对他们来说,最好是立即得到一个他们可以修复的错误,而不是默默地给出错误的值。

如果 希望将其截断为 int,那么通过首先通过 float传递它,然后根据需要调用 introundtruncfloorceil中的一个来显式地执行这一操作是很简单的。这也使您的代码更加自我记录,防止后来的修改“纠正”一个假设的无声地截断 intfloat的调用,方法是清楚地表明四舍五入值 是您想要的。

没有 特别的的原因。Python 只是简单地应用了不执行隐式转换的一般原则,而隐式转换是导致问题的众所周知的原因,尤其是对于 Perl 和 Javascript 等语言中的新手来说。

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

为了使 int("3.1459")返回 3,解释器必须隐式地将字符串转换为浮点数。因为 Python 不支持隐式转换,所以它选择引发异常。

简单来说,它们不是同一个函数。

  • Int (十进制)表现为‘ floor,即去掉小数部分并返回 int’
  • Int (string)表现为“此文本描述整数,将其转换并返回为 int”。

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

“ int”简短易记,对于大多数程序员来说,它应用于每种类型的意义是直观的,这就是他们选择它的原因。

这并不意味着它们提供了相同或组合的功能,它们只是具有相同的名称并返回相同的类型。它们可以很容易地被称为“ floorDecimalAsInt”和“ ConvertStringToInt”,但是它们使用“ int”是因为它很容易记住,(99%)直观和混淆很少发生。

将文本解析为包含小数点(如“4.5”)的整数,会在计算机语言的 大多数中抛出一个错误,程序员的 大多数也会抛出一个错误,因为文本值并不代表整数,并且暗示它们提供了错误的数据

有时候思想实验是有用的。

  • 行为 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')都只涉及一个转换。


编辑:

实际上,上面的代码无法处理某些角落情况: 1e-21E-2也都是浮点值。