关于python中的+、+=、*、*=

不废话,直接干货

1.了解一下python的内存机制

a=1
b=1
id(a)=id(b)    #短的字符串,数字python在内存中是一个对象
         
a=[]
b=[]
id(a)!=id(b)      #字典,数组这样的对象在内存中python会创建两个不同的对象
   
a="new a string"
b="new a string"   
id(a)!=id(b)       #长的字符串python在内存中同样会创建两个不同的对象

2.python中万物皆对象(很简单的一句话,也是最核心的一句话)

# 不可变类型
>>>a = 'wangjunjie'
>>>id(a)
4324743920
>>>a += '0817'
>>>id(a)
4324744944
>>>a = a + '0817'
>>>id(a)
4324750584
# 可变类型
>>>my_list = [1, 2, 3]
>>>my_list
[1, 2, 3]
>>>id(my_list)
4324743240
>>>my_list += [4, 5, 6]
>>>my_list
[1, 2, 3, 4, 5, 6]
>>>id(my_list)
4324743240
>>>my_list = my_list + [7, 8, 9]
>>>my_list
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>id(my_list)
4324744136

简单总结上面显示结果的几个重要结论:
1.变量分为不可变类型和可变类型,字符串、元组、整型、浮点型等数字都是不可比那类型,字典、列表、集合是可变类型
2.对于不可变类型,无论是执行a = a+b还是a += b,a的内存地址都会变,可以理解为生成了新的变量;
那对于可变类型,执行my_list = my_list + new_list时,my_list的内存地址发生变化,即my_list变成了一个新的变量;但是在执行my_list += new_list的时候,my_list内存地址不会发生变化,即没有生成新的变量,这种方法效果等类似于列表的extend操作。

**这里有一个例外的类型,小伙伴们要重视,那就是str,str是有__iadd__方法的,只不过不像列表一样地址ID不变,str的地址是会变的

3.两种方法的python底层原理

从方法的背后魔法方法可以清楚的解释这种现象:
+=背后的魔法方法是__iadd__
+背后的魔法方法是__add__
如果一个类,没有实现__iadd__方法的话,python就会退一步调用__add__方法
总体来说,可变类型都有__iadd__方法,而不可变类型没有__iadd__方法
为了方便记忆,我自己是这么记的:=单独出现的作用一般是赋值操作,所以a = a + b实际上就是python帮我们算出来a + b的值之后赋值给了变量a,在python眼中,这两个a本身就是两个毫无关联的对象。

4.举个栗子更好的理解这个问题

>>>my_tuple = (1, 2, [3, 4])
>>>my_tuple[2] += [5, 6]

思考一下此时my_tuple的值

>>> my_tuple = (1, 2, [3, 4])
>>> my_tuple[2] += [5, 6]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> my_tuple
(1, 2, [3, 4, 5, 6])
>>> 

猜对了吗?实际上,这里面有两个点,第一个是元组不可变,python确实报错了,但是my_tuple中的列表呢?第二个是实际上元组中的列表只是一个列表对象内存地址的引用而已,所以在执行my_tuple[2] += [5, 6]时候,列表的值被改变了!

注意一下:以上这个报错用my_tuple[2].extend([5, 6])不会报错,这并不违背元组是不可变的原则,因为引用地址确实没变,只不过地址里面的值,已经发生变化了!

5.* 和 *=

其实,这两个和+、+= 基本一样,只不过背后的魔法方法是__imul__和__mul__而已,就这么简单~

### Python中`=+`与`+=`的区别 在Python编程语言中,`=+`实际上是分两部分理解:一个是赋值运算符 `=` ,另一个是正号 `+` 。它表示将右侧表达式的正值赋予左侧变量。然而,这种形式并不常见,通常会引发混淆。 另一方面,`+=`是一个复合赋值运算符,用于将右侧的值与左侧变量相加并将结果重新赋回给该变量[^1]。具体来说: #### 语法定义 - **`=+`**: 它并不是一个独立的运算符组合,而是由赋值 (`=`) 和一元正号 (`+`) 组成。例如: ```python a = +5 ``` 上述语句的作用是对数值取正值并赋值给变量a。如果变量已经存在,则此操作不会改变其原有值[^3]。 - **`+=`**: 此为一种增量赋值方式,简化了传统先计算再赋值的过程。比如下面的例子展示了如何利用`+=`来更新列表或者字符串等内容。 ```python b = 2 b += 3 # 等价于 b = b + 3 ``` #### 应用场景对比 对于不可变数据类型(如整数、浮点数等),两者行为相似,都是基于原始值得到新值后再存储回去;但对于可变容器类对象而言(`list`, `dict`等等),则可能存在差异因为它们可能重载了特殊方法(__iadd__)从而实现原地修改而非创建副本: ```python lst = [1, 2] lst += [3, 4] # 调用了 lst.__iadd__([3, 4]) 如果支持的话,否则退化为 lst = lst + [3, 4] # 相当于执行如下代码片段 if hasattr(lst, '__iadd__'): result = lst.__iadd__([3, 4]) else: result = lst + [3, 4] del lst[:] lst.extend(result) ``` 另外值得注意的是关于单目增加的情况,在标准库里面并没有提供像C/C++那样的前置/后置自增功能(++x 或者 x++),但是可以通过连续两次应用加法达到类似效果[^2]: ```python count = 0 count = ++count # 解析为 count = (+ (+ count)) 即保持不变仍等于零 print(count) # 输出 '0' ``` 综上所述,虽然表面上看起来简单明了,但在实际开发过程中还是应该谨慎对待这些细节之处以免引入难以察觉错误!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值