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是一个常量,在内存中只有一个位置,所以a和b指向同一个位置。给常量分配内存地址时,先看内存空间中有没有哪个地方存储这个常量,如果有就用现有的,没有的话再去分配一个。浮点数同理,如果把上面代码的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没有疑问。重点讨论第二个:列表是可变对象,给列表分配内存地址时总是去找一个新的地址,所以a和c的地址不同。
如果想让a和c的地址相同呢?办法如下。
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。
如果我就是不想让a、b在同一个地址呢?方法如下。
a = (1, 2, 3)
b = tuple(list(a))
print(id(a)==id(b)) # False
is语句
有两个操作数,检测它们的内存地址是否相同,结果为True或False。例如下面两句等效:
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
在Python中,任何一个量(包含常量和变量)都是一个Object(对象)。所以,object这个数据类型涵盖所有的数据类型,包括Python内置的数据类型和你自己定义的数据类型(类)。事实上,Python的所有数据类型都是类(class)。
但并不是说,被object涵盖的数据类型是object的子类(继承类)。比如int类型的定义是class int:,而不是class int(object):。
涵盖数据类型的数据类型有很多,比如iterable,就涵盖所有可以迭代(遍历)的数据类型,最典型的就是列表、元组。再比如callable,涵盖所有可以被调用的数据类型,即函数(函数名),任何参数类型、返回类型的函数都可以。 ↩︎

8212

被折叠的 条评论
为什么被折叠?



