id()——Python内存地址分配机制初探

id()——取地址

对于id()的定义是:

def id(obj: object, /) -> int: ...

传入参数的类型为object1,返回值为int类型。

示例:

print( id(3) )
a = 3.5
print( id(a) )
print( id( type(a) ) )

整数、浮点数

a = 3
b = 3
print(id(a) == id(b))  # True

3是一个常量,在内存中只有一个位置,所以ab指向同一个位置。给常量分配内存地址时,先看内存空间中有没有哪个地方存储这个常量,如果有就用现有的,没有的话再去分配一个。浮点数同理,如果把上面代码的3都换成3.5,打印出来的还是True

列表

a = [1, 2, 3]
b = [4, 5, 6]
c = [1, 2, 3]
print(id(a)==id(b)) # False
print(id(a)==id(c)) # False

第一个输出是False没有疑问。重点讨论第二个:列表是可变对象,给列表分配内存地址时总是去找一个新的地址,所以ac的地址不同。

如果想让ac的地址相同呢?办法如下。

a = [1, 2, 3]   # 盒子a装着[1, 2, 3]这个列表
c = a           # 将a赋值给c,那么盒子c装着盒子a,a、c指向同一个位置
print(id(a)==id(c)) # True

把变量比喻成盒子。大盒子套小盒子,两个盒子当然在同一个地方。将a赋值给c,也就是说,盒子c装着盒子a,a和c地址相同。

再做一个有趣的实验——取索引。

a = [1, 2, 3]  
b = a[:]      
print(id(a)==id(b)) # False

解释:a[:]属于取多个索引的操作,结果为一个列表,分配新的地址,所以输出为Flase

元组

a = (1, 2, 3)
b = (1, 2, 3)
print(id(a)==id(b)) # True

同整数和浮点数,元组是不可变对象,在内存中只有一个位置,所以输出为True。

如果我就是不想让ab在同一个地址呢?方法如下。

a = (1, 2, 3)
b = tuple(list(a))
print(id(a)==id(b)) # False

is语句

有两个操作数,检测它们的内存地址是否相同,结果为TrueFalse。例如下面两句等效:

print( a is b)
print( id(a) == id(b))

特别注意is==的区别。前者问的是“盒子a是盒子b吗”,后者问的是"a和b这两个盒子装的东西一样吗“?我的盒子(a)装苹果,你的盒子(b)也装苹果(a == b为True) ;但我的盒子和你的盒子是两个盒子(a is b 为False)。如果我的盒子和你的盒子是一个盒子(我们两个共用一个盒子)(a is b 为True),那么我们盒子里装的东西一定是一样的(a ==b为True)。(a is b ⇒ \Rightarrow a == b,反过来不成立)

可以做下面的实验加深理解:

a = [1, 2, 3]
b = [1, 2, 3]
print(a == b) # False
print(a is b) # False

  1. 在Python中,任何一个量(包含常量和变量)都是一个Object(对象)。所以,object这个数据类型涵盖所有的数据类型,包括Python内置的数据类型和你自己定义的数据类型(类)。事实上,Python的所有数据类型都是类(class)。
    但并不是说,被object涵盖的数据类型是object的子类(继承类)。比如int类型的定义是class int:,而不是class int(object):
    涵盖数据类型的数据类型有很多,比如iterable,就涵盖所有可以迭代(遍历)的数据类型,最典型的就是列表、元组。再比如callable,涵盖所有可以被调用的数据类型,即函数(函数名),任何参数类型、返回类型的函数都可以。 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值