Python: 变量 += 和 变量 = 变量 +

+= 和 = + 的内部实现:

为了方便起见:a += 1 和 a = a + 1 这两种形式在本文中被缩写为 += 和 =+。

+= 在内部的方法是: __iadd__
=+ 在内部的方法是: __add__

如果一个类,没有实现 __iadd__ 方法的话,python 就会退一步调用 __add__ 方法
总体来说,可变类型都有 __iadd__ 方法,而不可变类型没有 __iadd__ 方法

不可变类型:

a = 1
print(id(a))
a += 1
print(id(a))
a = a + 1
print(id(a))
print('*'*15)

b = 1.5
print(id(b))
b += 1.1
print(id(b))
b = b + 1.1
print(id(b))
print('*'*15)

c = 'abc'
print(id(c))
c += 'd'
print(id(c))
c = c + 'e'
print(id(c))
print('*'*15)

d = (1, 2, 3)
print(id(d))
d += (4,)
print(id(d))
d = d + (5,)
print(id(d))
print('*'*15)

print(dir(a))
print(dir(b))
print(dir(c))
print(dir(d))

结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们发现除了字符串型 str 有意外之外,别的都符合不可变对象的性质。一个对象如果是不可变对象,那么创建之后就无法修改,我们看着的 += 和 =+ 都是创建了一个新的对象,然后赋值给相应的值,最后变量名重新指向。
这里的特例就是 str 的 =+ ,我们发现 str 的 =+ 方法是在原有的基础上面修改的,一开始我以为是 str 类实现了 __iadd__ 方法,但是我用 dir() 方法查看 c 包含的属性和方法之后发现并没有实现。具体的原因我还没有找到,如果有大佬知道原因的请指教。

可变类型

考虑到集合 set 和字典 dict 没有 + 操作,我们在 list 上面测试:

a = [1, 2, 3]
print(id(a))
a += [4]
print(id(a))
a = a + [5]
print(id(a))
print('*'*15)

结果如下:
在这里插入图片描述
我们发现 list 对象的 += 是在自身操作的,=+ 和可变对象一样,是新建一个对象,然后把 + 之前列表元素和要加的元素依次放进去的。这里还有一个就是时间的效率问题。

import time


def test1():
    a_list = []
    start_time = time.time()
    for i in range(100000):
        a_list += [i]
    end_time = time.time()
    print('Time1: ', end_time - start_time)
    return a_list


def test2():
    b_list = []
    start_time = time.time()
    for i in range(100000):
        b_list = b_list + [i]
    end_time = time.time()
    print('Time2: ', end_time - start_time)
    return b_list


def test3():
    c_list = []
    start_time = time.time()
    for i in range(100000):
        b_list = c_list.extend([i])
    end_time = time.time()
    print('Time3: ', end_time - start_time)
    return c_list


test1()
print('*'*30)
test2()
print('*'*30)
test3()

结果如下:
在这里插入图片描述
我们额外加了一个 extend() 方法,我们发现 += 和 extend() 方法比 =+ 快很多,因为不用新建对象和删除对象,以及最耗时的将原有列表的值复制过来的过程。最后用 dir() 方法发现 list 对象中有 __iadd__ 方法。顺便提一句 extend 方法中参数代表的列表不会有变化,即 a.extend(b) 操作之后,b 没有任何变化。

总结

  1. 首先排除例外 str 对象的 =+ 方法
  2. 不可变对象的 += 和 =+ 和期望的一样,都需要新建对象来操作,除了例外:str 的 =+ 方法是在原来对象上操作的。不可变对象没有实现 __iadd__ 方法。
  3. 可变对象的 += 是在原有对象上修改扩展,速度快;而 =+ 则需要新建一个对象,然后复制和添加操作,速度慢;可变对象实现了 __iadd__ 方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值