• 【Python】序列的增量赋值


    增量赋值运算符有 += 和 *=。+= 背后的特殊方法是 __iadd__,如果一个类没有实现 __iadd__ 方法,Python 会退一步调用 __add__ 方法。这两个方法的区别在于,__iadd__ 为就地改动,不会改变原值的内存地址,而 __add__ 方法会得到一个新对象。

    考虑下面一个表达式:

      a += b

    如果 a 实现了 __iadd__ 方法,a 会就地改动(内存地址不变)。如果 a 没有实现 __iadd__ 方法,那么 a += b 这个表达式的效果就变得跟 a = a + b 一样了,生成一个新的对象赋给 a。

    总体来讲,可变序列一般都实现了 __iadd__ 方法,因此 += 是就地加法,而不可变序列根本就不支持这个操作。

    *= 和 += 一样,只是背后的特殊方法为 __imul__。

    a = [1, 2, 3]
    b = [4, 5, 6]
    print("id(a) = %d" % id(a))
    a += b
    print("id(a) = %d" % id(a))
    
    c = [1, 2, 3]
    print("id(c) = %d" % id(c))
    c = c + b
    print("id(c) = %d" % id(c))
    
    d = (1, 2, 3)
    print("id(d) = %d" % id(d))
    d *= 2
    print("id(d) = %d" % id(d))

    运行结果如下:

    id(a) = 1298277978824
    id(a) = 1298277978824
    id(c) = 1298277978696
    id(c) = 1298277978632
    id(d) = 1298277972872
    id(d) = 1298277136616

     

    了解了序列的增量赋值,我们来看 Leonardo Rochael 在 2013 年的 Python 巴西会议上提到的谜题:

    t = (1, 2, [30, 40])
    t[2] += [50, 60]

    A. t 变成 (1, 2, [30, 40, 50, 60])

    B. 因为 tuple 不支持对它的元素赋值,所以会抛出 TypeError 异常

    C. 以上两个都不是

    D. A 和 B 都是对的

     

    估计很多人会跟我一样选 B,但其实答案是 D。在控制台运行代码,显示结果如下:

    总结:

    1、对不可变序列进行重复拼接操作的话,效率会很低,因为每次都要新建一个序列,然后把原来序列中的元素复制到新的序列里,然后再追加新的元素。

    2、不要把可变对象放在元组里面。

    3、增量赋值不是一个原子操作,我们刚才也看到了,它虽然抛出了异常,但 t 的值还是改变了。

  • 相关阅读:
    设计模式享元模式实现C++
    并查集
    设计模式代理模式实现C++
    设计模式装饰模式实现C++
    最小生成树Prim算法实现
    图的邻接矩阵存储
    威佐夫博弈(Wythoff Game)初识 HDU 1527 POJ 1067
    设计模式原型模式实现C++
    三种经典博弈问题 BashGame;WythoffGame;NimmGame;
    设计模式外观模式实现C++
  • 原文地址:https://www.cnblogs.com/gl1573/p/9744460.html
Copyright © 2020-2023  润新知