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


83

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

int(1.23)
1

当且仅当字符串是整数文字时,int(string)才返回int。

int('1.23')
ValueError

int('1')
1

有什么特殊原因吗?我发现在一种情况下功能处于下限,而在另一种情况下则没有功能。

Answers:


123

没有特别的原因。Python只是简单地运用了不执行隐式转换的一般原理,隐式转换是众所周知的问题原因,尤其是对于新手来说,使用Perl和Javascript这样的语言。

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

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


type(3)返回<type int>。但是,python没有抱怨float("3")。python不是将字符串隐式转换为int然后转换为float吗?
franksands

否。“ 3”是有效的浮点值,即使作为程序文字它也会被解释为整数。无需整数转换。
holdenweb '19

75

几乎可以肯定,这是应用Python Zen中的三个原理的情况

显式隐式更好。

实用性胜过纯度

错误绝不能默默传递

在某个百分比的时间内,某人正在int('1.23')为他们的用例调用错误的转换,并且想要类似floatdecimal.Decimal替代的东西。在这些情况下,让他们立即解决并修复错误,而不是默默提供错误的值,这显然更好。

在你的情况下需要截断为int,它是微不足道的,将其通过明确地这样做float,然后再调用之一introundtruncfloorceil适当的。这也使得代码更自我记录,防范以后修改“纠正”的假想默默-截断int呼吁float通过明确的舍入值你想要的。


我认为这些原则早在禅宗制定之前就已被采用,但是无论哪种方式,两者似乎都是和谐的。
holdenweb

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')每个仅涉及一次转化。


编辑:

实际上,在某些极端情况下,上面的代码无法处理:1e-2并且1E-2都是浮点值。


需要说明的是:我不建议行为B,因为这很危险,正如您和其他人所说。我不确定是否有比当前解决方案更好的解决方案。一种选择是为函数赋予不同的名称,但这只是要键入的内容。在动态类型化语言中,使int(1.23)失败并且仅将int(float-with-no-decimal-places)返回整数的明显解决方案没有意义。
StefanS '16

1
极端情况可能是int('123E-2')int('1L')
Jared Goguen '16

11

简而言之-它们不是相同的功能。

  • int(decimal)的行为类似于“ floor,即舍去小数部分并返回为int”
  • int(string)的行为类似于“此文本描述了一个整数,将其转换为int并返回”。

它们是两个具有相同名称的不同函数,它们返回一个整数,但它们是不同的函数。

“ int”简短易记,对于大多数程序员来说,它对每种类型的含义都很直观,这就是为什么他们选择它。

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

对于包含小数点(例如“ 4.5”)的文本,将文本解析为整数将在大多数计算机语言中引发错误,并且大多数程序员期望会引发错误,因为文本值不表示整数并且表示他们提供错误的数据


2
那么为什么两个“不同的函数”具有相同的名称?听起来像是对禅宗的胡说八道。
霍布斯

因为该名称对2种不同的功能有意义并且简洁。整数

从技术上讲,记住这int是一种类型(并在其中内置一个)可能会有所帮助。它的创建者(__new__)采用多种可能的参数类型。每种类型的行为都是明确定义的。
holdenweb'6

如上所述,这个答案是完全错误的。int实际上,它不是一个函数,而是一个类型,其__new__and__init__方法采用字符串或float参数,并对其进行适当处理。准确地说,类型对两种参数类型的处理方式不同,但是只有一种int
holdenweb
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.