Python中对象可变的(mutable)和不可变的(immutable)介绍

Python中对象可变的(mutable)和不可变的(immutable)介绍

Python中所有的数据都可以被视为对象。在Python中,一切皆对象,包括整数、浮点数、字符串、列表、字典等内置数据类型,也包括自定义的类和对象。

每个对象都有自己的属性和方法,可以通过点操作符来访问和调用。例如,整数对象有属性如大小、位数等,还有方法如转换为字符串、求和等。字符串对象有属性如长度、字符的索引等,还有方法如拼接、大小写转换等。

Python中的对象分为可变的(mutable)和不可变的(immutable)

Python 中每个对象(object)都有各自的标识(identity)、类型(type)和值(value)。一个对象被创建后,它的标识就绝不会改变;你可以将其理解为该对象在内存中的地址(address )。“is” 运算符可以比较两个对象的标识号是否相同;id() 函数能返回一个代表其标识的整数。

有些对象的 值 可以改变。值可以改变的对象被称为 可变的(mutable);值不可以改变的对象就被称为 不可变的(immutable)。(一个不可变容器对象如果包含对可变对象的引用,当后者的值改变时,前者的值也会改变;但是该容器仍属于不可变对象,因为它所包含的对象集是不会改变的。因此,不可变并不严格等同于值不能改变,实际含义要更微妙。) 一个对象的可变性是由其类型决定的;例如,数字、字符串和元组是不可变的,而字典和列表是可变的。https://docs.python.org/zh-cn/3/reference/datamodel.html#objects-values-and-types

可变(mutable)类型的对象可以在创建后进行修改,其值可以改变,但对象的标识(identity)保持不变。常见的可变类型包括列表(list)、字典(dict)、集合(set)等。例如,我们可以通过修改列表的元素来改变列表的值。

my_list = [1, 2, 3]

my_list[0] = 4

print(my_list)  # 输出 [4, 2, 3]

不可变(immutable)类型的对象在创建后不能被修改,任何修改操作都会返回一个新的对象。常见的不可变类型包括整数(int)、浮点数(float)、字符串(str)、元组(tuple)等。例如,我们无法直接修改字符串的某个字符,而只能通过切片和拼接等操作来创建新的字符串对象。

my_string = "Hello"

new_string = my_string + " World"

print(new_string)  # 输出 "Hello World"

需要注意的是,对象的可变性是指对象本身是否可以被修改,而不是对象所引用的变量是否可以被修改。对于不可变类型的变量,我们可以将其重新赋值为新的对象,但原始对象的值仍然保持不变。

my_string = "Hello"

my_string = my_string + " World"

print(my_string)  # 输出 "Hello World"

可变和不可变类型在内存中的存储方式和使用方法也有所不同,这会影响到对象的性能和使用方式。在编写代码时,需要根据具体需求和性能考虑使用可变或不可变类型。

特别说明

由于 Python 中的变量存放的是对象引用,所以对于不可变对象而言,尽管对象本身不可变,但变量的对象引用是可变的。运用这样的机制,有时候会让人产生糊涂,似乎可变对象变化了——变化的情况实际上是由于变量重新指向了新的对象,而不是修改了原来的对象。如下面的代码:

i = 73 

i += 2

不可变的对象的特征没有变,依然是不可变对象,变的只是创建了新对象,改变了变量的对象引用。参见下图:

​对于可变对象,其对象的内容是可以变化的。当对象的内容发生变化时,变量的对象引用是不会变化的。如下面的例子。

m=[5,9] 

m+=[6]

参见下图:

​【Mutable(可变)对象

可变对象可以在其 id() 保持固定的情况下改变其取值。

Immutable(不可变)对象

具有固定值的对象。不可变对象包括数字(numbers)、字符串(strings)和元组(tuples)。这样的对象不能被改变。如果必须存储一个不同的值,则必须创建新的对象。不可变对象不允许对自身内容进行修改。如果我们对一个不可变对象进行赋值,实际上是生成一个新对象,再让变量指向这个对象。哪怕这个对象简单到只是数字 0 和 1。】

下面程序演示了不可变参数传递的情况:

def add_fun(num):

    num +=1

    print(num, id(num))

    return

num = 3

add_fun(num)

print(num, id(num))

【顺便提示:id()的值不是固定不变的——此值系统为对象分配的内存地址,在你练习时显示的不同值是正常的。】

这段代码运行结果是:

4 1857150478736
3 1857150478704

不可变的对象的特征没有变,依然是不可变对象,变的只是创建了新对象,改变了变量的对象引用。

下面程序演示了可变参数传递的情况:

def list_append_fun(list_t):

    list_t.append("abc")

    print(list_t, id(list_t))

    return

list_t = [1,2,3]

print(list_t, id(list_t))

list_append_fun(list_t)

print(list_t, id(list_t))

这段代码运行结果是:

[1, 2, 3] 2005885237248
[1, 2, 3, 'abc'] 2005885237248
[1, 2, 3, 'abc'] 2005885237248

当传递列表或者字典时,如果改变引用的值,就改变了原始对象。对于可变对象参数,其对象的内容是可以变化的。当对象的内容发生变化时,变量的对象引用是不会变化的。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习&实践爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值