【问题标题】:How are Python in-place operator functions different than the standard operator functions?Python 就地运算符函数与标准运算符函数有何不同?
【发布时间】:2011-01-23 08:44:34
【问题描述】:

来自docs

许多操作都有“就地” 版本。以下功能 提供更原始的访问 就地运营商比平时 语法可以;例如, 语句 x += y 等价于 x = 运算符.iadd(x, y)。另一种方法 也就是说z = operator.iadd(x, y) 等价于 复合语句 z = x; z += y。

问题:

  • 为什么operator.iadd(x, y) 不等同于z = x; z += y

  • operator.iadd(x, y)operator.add(x, y) 有何不同?

Related question,但我对 Python 类方法不感兴趣;只是内置 Python 类型上的常规运算符。

【问题讨论】:

    标签: python function operator-keyword


    【解决方案1】:

    首先,你需要了解__add____iadd__的区别。

    对象的__add__ 方法是常规加法:它接受两个参数,返回它们的和,并且不修改任何一个参数。

    一个对象的__iadd__ 方法也接受两个参数,但是在原地进行更改,修改第一个参数的内容。因为这需要对象变异,所以不可变类型(如标准数字类型)不应该有 __iadd__ 方法。

    a + b 使用__add__a += b 使用 __iadd__(如果存在);如果没有,它会通过__add__ 模拟它,如tmp = a + b; a = tmpoperator.addoperator.iadd 的区别相同。

    对于另一个问题:operator.iadd(x, y) 不等同于z = x; z += y,因为如果不存在__iadd__,则将使用__add__。您需要分配值以确保在两种情况下都存储结果:x = operator.iadd(x, y)

    你自己很容易看到这一点:

    import operator
    a = 1
    operator.iadd(a, 2)
    # a is still 1, because ints don't have __iadd__; iadd returned 3
    
    b = ['a']
    operator.iadd(b, ['b'])
    # lists do have __iadd__, so b is now ['a', 'b']
    

    【讨论】:

    • docs.python.org/2/reference/datamodel.html#object.__iadd__ 请注意,增强分配可以但不必就地修改对象
    • 为什么 python 在设计时使用了就地操作的增强赋值?这有点违反直觉,因为当我们学习语言时,我们通常首先学习具有不可变值的增强赋值。所以有点出乎意料的是,对于可变值,增强赋值的行为会有所不同。感觉相当隐晦且容易出错。
    • @max:我不知道你为什么声称“当我们学习语言时,我们通常首先学习具有不可变值的增强赋值”。字符串是不可变的,数值是可变的,列表是可变的,元组是不可变的。 s = 'foo's += 'bar' 的行为显然不同于 x = 4.2 x += 2l = [1,5,6] l += [2]。唯一容易混淆的地方是您不知道 LHS 值的类型。
    • @max 这听起来像是设计学习材料的人的错。增广赋值的目的很明确:PEP 203
    【解决方案2】:

    也许是因为某些 Python 对象是不可变的。

    我猜operator.iadd(x, y) 相当于 z = x; z += y 仅适用于字典和列表等可变类型,但不适用于数字和字符串等不可变类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-05
      • 2013-07-20
      • 2021-02-07
      • 2012-04-07
      • 1970-01-01
      相关资源
      最近更新 更多