【问题标题】:Counterintuitive behaviour of int() in pythonpython中int()的反直觉行为
【发布时间】:2016-07-05 06:07:31
【问题描述】:

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

int(1.23)
1

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

int('1.23')
ValueError

int('1')
1

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

【问题讨论】:

    标签: python


    【解决方案1】:

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

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

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

    【讨论】:

    • type(3) 返回<type int>。但是,python 并没有抱怨float("3")。 python不是隐式将字符串转换为int然后再转换为float吗?
    • 没有。 “3”是一个有效的浮点值,即使作为程序文字它会被解释为整数。不需要整数转换。
    【解决方案2】:

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

    显式最好是隐式。

    [...] 实用胜过纯粹

    错误不应该默默地过去

    在某些情况下,执行int('1.23') 的人会为他们的用例调用错误的转换,而是想要floatdecimal.Decimal 之类的东西。在这些情况下,他们显然最好立即获得可以修复的错误,而不是默默地给出错误的值。

    如果您确实想要将其截断为 int,通过首先将其传递给 float,然后调用 int、@ 中的一个来显式地这样做是微不足道的987654327@、truncfloorceil(视情况而定)。这也使您的代码更具自我记录性,防止以后的修改“纠正”假设的静默截断 int 调用 float 通过明确舍入值 你想要什么.

    【讨论】:

    • 我认为这些原则早在禅宗形成之前就已被采纳,但无论哪种方式,这两者似乎都是和谐的。
    【解决方案3】:

    有时思想实验会很有用。

    • 行为 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 也是浮点值。

    【讨论】:

    • 澄清一下:我不会建议行为 B,因为正如你和其他人所说的那样,这很危险。我不确定是否存在比当前更好的解决方案。一种选择是为函数赋予不同的名称,但这只是要键入的内容更多。让 int(1.23) 失败并且只有 int(float-with-no-decimal-places) 返回整数的明显解决方案在动态类型语言中没有意义。
    • 角盒可能是int('123E-2')int('1L')
    【解决方案4】:

    简单来说 - 它们不是同一个功能。

    • int(decimal) 表现为“下限,即去掉小数部分并返回为 int”
    • int(string) 表现为“此文本描述了一个整数,将其转换并返回为 int”。

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

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

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

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

    【讨论】:

    • 那为什么两个“不同的函数”有相同的名字呢?听起来像是违反了一些禅宗废话。
    • 因为名称对 2 个不同的功能有意义且简洁。 int-ify 一个小数(下限),将字符串转换为 int(转换)
    • 从技术上讲,记住int 是一种类型(并且是内置类型)可能会有所帮助。它的创建者 (__new__) 采用了许多可能的参数类型。它对每种类型的行为都是明确定义的。
    • 这个答案是完全错误的。 int 实际上不是一个函数而是一个类型,其__new____init__ 方法接受一个字符串或浮点参数,并适当地处理每一个。更准确地说,该类型对两种参数类型的处理方式不同,但只有一个 int
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-16
    • 2019-05-29
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 2018-04-18
    相关资源
    最近更新 更多