int()在python中的违反直觉的行为
在文档中明确指出,int(数字)是一种地板types转换:
int(1.23) 1
和int(string)返回一个int当且仅当该string是一个整数文字。
int('1.23') ValueError int('1') 1
这有什么特别的理由吗? 我觉得这个function在一种情况下是有违直觉的,而不是在另一种情况下。
没有特别的理由。 Python只是简单地应用其不执行隐式转换的一般原则,这是众所周知的问题原因,特别是对于像Perl和Javascript这样的语言的新手而言。
int(some_string)
是将string转换为整数格式的显式请求; 此转换的规则指定该string必须包含有效的整数字面值expression式。 int(float)
是将float转换为整数的明确请求; 此转换的规则指定浮点的小数部分将被截断。
为了使int("3.1459")
返回3
,解释器将不得不隐式地将string转换为浮点数。 由于Python不支持隐式转换,因此它select引发exception。
这几乎可以肯定是一个应用Python的禅的三个原则的例子:
显式是更好的隐式。
实用性胜过纯净
错误不应该默默通过
某些时间百分比,某人在做int('1.23')
的时候,正在为它们的用例调用错误的转换,并且想要一些像float
或者decimal.Decimal
东西。 在这些情况下,他们立即得到一个可以解决的错误显然是更好的,而不是默默地给出错误的价值。
如果你想把它截断为一个int,那么通过首先将它传递给float
,然后根据需要调用int
, round
, trunc
, floor
或者ceil
来明确地做到这一点是微不足道的。 这也使得你的代码更加自我logging,防止后来的修改“纠正”一个假设的静静地截断int
调用float
通过明确说明四舍五入的值是你想要的。
有时候思想实验可能会有用。
- 行为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)
(甚至在上面的代码中,我也没有完全的信心,认为没有任何error handling的情况)。
行为A因此比行为B更具performance力
另一件要考虑的事情是: '1.23'
是一个浮点值的string表示forms。 将'1.23'
转换为一个整数在概念上涉及两次转换(将string转换为整数),但是int(1.23)
和int('1')
每次只涉及一次转换。
编辑:
事实上,上面的代码不能处理的angular落情况: 1e-2
和1E-2
也都是浮点值。
简而言之 – 它们不是相同的function。
- int(十进制)performance为“floor”,即敲除小数部分并返回为“int”
- int(string)performance为“这个文本描述一个整数,将其转换并返回为int”。
它们是2个不同的函数,它们具有相同的名称 ,它们返回一个整数,但它们是不同的函数
“int”简短易记,适用于每种types的含义对于大多数程序员来说是直观的,这就是为什么他们select它。
没有暗示他们提供相同或组合的function,他们只是具有相同的名称并返回相同的types。 他们可以很容易地被称为“floorDecimalAsInt”和“convertStringToInt”,但他们去了“int”,因为它很容易记住,(99%)直观和混乱很less发生。
将文本parsing为包含小数点(例如“4.5”)的文本的整数将在大多数计算机语言中引发错误,并且被大多数程序员抛出错误,因为文本值并不代表整数并且意味着他们提供的是错误的数据