资讯专栏INFORMATION COLUMN

Python中的可变与不可变对象

wizChen / 3302人阅读

摘要:中的可变与不可变对象中的所有东西都是一个对象。和内置函数以整数形式返回对象的标识。更改可变对象很便宜。不可变的例外并非所有的不可变对象都是不可变的。所以引用该对象的变量不会改变,但对象本身正在改变,但仅在函数范围内。

Python中的可变与不可变对象

Python中的所有东西都是一个对象。每个Python新手都应该学习的是,Python中的所有对象都可以是可变的或不可变的。

让我们更深入地了解它的细节...因为Python中的所有东西都是对象,所以每个变量都包含一个对象实例。当一个对象被初始化时,它被分配一个唯一的对象ID。它的类型是在运行时定义的,一旦设置永远不会改变,但是如果它是可变类型它的状态是可以被改变的。简单地说,一个可变对象可以在创建之后被改变,一个不可变对象不能。

诸如(int,float,bool,str,tuple,unicode)等内置类型的对象是不可变的。像(list,set,dict)这样的内置类型的对象是可变的。自定义类通常是可变的。要模拟类中的不变性,应该覆盖属性设置和删除以引发异常。

现在出现这个问题,我们如何确定我们的变量是一个可变对象还是不可变对象。为此,我们应该了解“ID”和“TYPE”函数的用途。

ID和TYPE

内置函数id()以整数形式返回对象的标识。这个整数通常对应于对象在内存中的位置,虽然这是针对Python的实现和正在使用的平台而言。is运算符用来比较两个对象的标识。

内置函数type()返回一个对象的类型。让我们看一个简单的例子

"""示例1""" 
>>> x =“Holberton” 
>>> y =“Holberton” 
>>> id(x)
140135852055856 
>>> id(y)
140135852055856 
>>> print(x is y)" ""比较类型""" 
真的
"""示例2""" 
>>> a = 50 
>>> type(a)
 
>>> b =“Holberton” 
>>> type(b)

现在我们已经看到了如何比较两个简单的字符串变量来找出类型和ID。因此,使用这两个函数,我们可以检查不同类型的对象是如何与变量相关联以及如何更改对象的。

可变和不可变的对象

正如我们前面所讨论的,一个可变对象可以改变它的状态或内容,不可变对象不能。

可变对象
列表,字典,集,字节数组

不可变对象
int,float,complex,string,tuple,frozen set [注:set的不可变版本],bytes

一个实用的例子来找出对象类型的可变性

x = 10
x = y

我们正在创建一个int类型的对象。标识符x和y指向同一个对象。

id(x)== id(y)
id(y)== id(10)

如果我们做一个简单的操作。

x = x + 1

现在

id(x)!= id(y)
id(x)!= id(10)

x被标记的对象被改变。对象10从未被修改过。不可变对象在创建后不允许修改

在可变对象的情况下

m = list([1,2,3])
n = m

我们正在创建一个类型列表的对象。标识符m和n被标记为同一个列表对象,它是3个不可变的int对象的集合。

id(m)== id(n)

现在从列表对象中弹出一个元素确实会改变对象,

m.pop()

对象ID不会被更改

id(m)== id(n)

m和n将在修改后指向同一个列表对象。列表对象现在将包含[1,2]。

那么从上面的例子中我们看到了什么?

Python以不同方式处理可变对象和不可变对象。
不可变的访问比可变对象更快。
当你需要改变对象的大小,例如列表,字典等等时,可变对象是很好用的。当你需要确保你创建的对象始终保持不变时,使用不可变对象。
不可变对象对于“更改”而言基本上是昂贵的,因为这样做涉及到创建副本。更改可变对象很便宜。

不可变的例外..

并非所有的不可变对象都是不可变的。

如前所述,Python容器比如元组,是不可变的。这意味着一个tuple的值在创建后无法更改。但是元组的“值”实际上是一系列名称,它们与对象的绑定是不可改变的。关键点是要注意绑定是不可改变的,而不是它们绑定的对象。

让我们考虑一个元组t =("holberton",[1,2,3])

上面的元组t包含不同数据类型的元素,第一个元素是一个不可变的字符串,第二个元素是一个可变列表。元组本身不可变。即它没有任何改变其内容的方法。同样,字符串是不可变的,因为字符串没有任何可变方法。但是列表对象确实有可变方法,所以可以改变它。这是一个微妙的点,但是非常重要:不可变对象的“值” 不能改变,但它的组成对象是能做到改变的。

对象如何传递给函数

对于我们来说,了解可变类型和不可变类型之间的区别以及将它们传递到函数时如何处理是非常重要的。当使用正确的对象时,存储效率会受到很大影响。

例如,如果一个可变对象在函数中被引用调用,它可以改变原来的变量本身。因此为了避免这种情况,需要将原始变量复制到另一个变量中。不可变的对象可以通过引用来调用,因为它的值不能被改变。

def updateList(list1):
    list1 + = [10]
n = [5,6] 
print(id(n))#140312184155336
updateList(n)
print(n)#[ 
5,6,10 ] print(id(n))#140312184155336

从上面的例子我们可以看到,我们通过引用调用了列表,因此对原始列表本身进行了更改。

让我们看看另一个例子:

def updateNumber(n):
    print(id(n))
    n + = 10
b = 5 
print(id(b))#10055680 
updateNumber(b)#10055680 
print(b)#5

在上面的例子中,同一个对象被传递给函数,但即使对象是相同的,变量值也不会改变。这被称为按价值传递 。那么到底发生了什么?当函数调用该值时,只传递该变量的值,而不传递该对象本身。所以引用该对象的变量不会改变,但对象本身正在改变,但仅在函数范围内。因此,这种变化没有体现出来。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41828.html

相关文章

  • 可变对象与不可变对象

    摘要:不可变对象不允许对自身内容进行修改。因为他们说到不可变对象时用的是赋值,而说到可变对象又用了的索引等方法,这根本是两码事。基于这一设定,两者在功能上的最大区别就是不可变对象可以作为字典的键,而可变对象不行。 前阵子我们聊了下函数的参数传递以及变量赋值的一些内容:关于函数参数传递,80%人都错了 简单回顾下要点: 1. Python 中的变量不是装有对象的 容器 ,而是贴在对象上的 标签...

    jay_tian 评论0 收藏0
  • python程序员的基本素养--你从没见过的Python变量引用

    摘要:变量在我们的编程中是最基础的概念,它就相当于我们盖大楼用的砖块一样不可或缺。理解变量的运行方式至关重要。虽然他们的食物是一样的。但是,像这样这样并没有新建对象,而是将的引用传递给了,他们都指向一个对象。这个就是的垃圾回收机制。 变量在我们的编程中是最基础的概念,它就相当于我们盖大楼用的砖块一样不可或缺。理解变量...

    不知名网友 评论0 收藏0
  • python_bomb----数据类型总结

    摘要:数据类型有数字,字符串,值,列表,元组,集合,字典可变与不可变可变与不可变的区别对这个数据类型进行增删改差时,数据存储地址不变,不会开辟新的空间可变不开辟新空间不可变会改变内存地址不可变数据类型数字,字符串,值,元组可变数据类型列表,集合, 数据类型 有:数字,字符串,bool值,列表,元组,集合,字典 可变与不可变 可变与不可变的区别:对这个数据类型进行增删改差时,数据存储地址不变,...

    dkzwm 评论0 收藏0
  • 经验拾忆(纯手工)=> Python基本数据类型

    摘要:不要疑惑,告诉你答案这个代表正负号的正。虽然一点技术含量没有,但是你要懂序列也许叫可迭代对象更为合适,但是我喜欢叫序列。 数据结构 可变类型与不可变类型(重头戏) 基操: 可变类型:[], {} # 可增删改 查 不可变类型: int float str () # 无法增删改, 只可查 升操: + 与...

    Andrman 评论0 收藏0
  • python深拷贝与浅拷贝

    摘要:之前关于的作用域赋值参数传递,我们接连谈了几篇文章全菊变量和菊部变量关于函数参数传递,人都错了可变对象与不可变对象今天我们依然要就相关话题继续下去。这是由于它们是不可变对象,不存在被修改的可能,所以拷贝和赋值是一样的。 之前关于 Python 的作用域、赋值、参数传递,我们接连谈了几篇文章: 全菊变量和菊部变量 关于函数参数传递,80%人都错了 可变对象与不可变对象 今天我们依然要...

    ideaa 评论0 收藏0

发表评论

0条评论

wizChen

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<