>>> a=5
>>> b=6
>>> id(a)
10914496
>>> id(b)
10914528
>>> c='Hello'
>>> d='World'
>>> id(c)
139973573252184
>>> id(d)
139973616356744
>>> e=(4>5)
>>> f=(4<5)
>>> id(e)
10739968
>>> id(f)
10740000
更新#1
>>> id(c)
139973616356856
>>> id(c[0])
139973652926112
>>> id(c[1])
139973653190728
>>> id(c[2])
139973653634272
>>> id(c[3])
139973653302104
我有这个疑问,因为我首先学习了C ++(说实话,Turbo C ++),并且在Python中定义字符串的地址的方式与C ++中发生的情况大不相同。我想这在Python中没问题,因为我们无法通过它在Python中的地址访问对象,我是对的吗?
另外,为c和c [0]设置不同的地址有什么意义?对于某些人来说,这些问题可能是不必要的,但我很想知道Python如何将地址分配给各种数据类型,特别是(此处)字符串。
答案 0 :(得分:2)
根据您计算机的体系结构,数据类型将以不同的字节长度存储在内存中。例如,字符串中的每个ASCII字符都需要一个字节来存储它,而整数可以存储在任何位长度中,最多可以存储,具体取决于所存储数字的大小。我并不完全确定,但python可能会在其分配的内存的不同区域存储不同的数据类型。
Python还会在其分配的内存中存储更多内容,而不仅仅是您提供的变量。 IDE也在该区域运行。因此,在两个分配之间可能存储了一些其他变量。
对于更新#1,请查看this
答案 1 :(得分:1)
id
碰巧是CPython中的地址是一个实现细节;它们只能保证与同时存在的对象不同。
您观察到的分组是因为CPython预先创建了许多对象,包括-5
到256
以及True
和False
。在通常情况下,这些值不会出现在任何其他地址,因为它们是不可变类型,所以可能会出现这种情况。
第二个问题,关于字符串中的切片,是因为Python的字符串对象不相互引用。没有字符类型,因此从字符串中提取字符会产生一个新字符串。同样,其中一些可能被缓存(实习字符串)。字符串对象的地址不一定是其内容的地址。
您可以使用ctypes
访问您熟悉的C类型,但这样做通常很尴尬且有风险。例如,如果将Python字符串传递给改变C字符串的函数,则会破坏字符串本身; Python期望字符串是不可变的,并且可以共享它们并缓存它们的哈希值。
答案 2 :(得分:1)
首先,我们应该从Python开始以与C相同的方式开始。在C中,数组只是一块内存。在Python中,它是一个对象。 id()
和c
的{{1}}与此结果不同。
其次,你应该意识到Python中的每件事都是一个对象。在C中,当您执行c[0]
之类的操作时,您将从一系列内存位置请求第一个值。在Python中,情况不一定如此。对于标准列表,它由数组支持,但其中的地址对您是隐藏的。你看到的是通过c[0]
的对象的地址。在这种情况下,id()
是一个字符串,但c
也是如此(Python中没有字符类型)。这意味着当您要求c[0]
时,Python正在创建一个新字符串来表示您请求的字符(或者更确切地说是子字符串)。幸运的是,Python并不是每次都实际创建一个新的字符串,因为Python会自动插入1个字符的字符串。
另外,请记住,Python对象具有结构并且也会消耗内存。关于C的最好的事情之一是能够非常控制内存布局,但是你在Python中失去了这个方面。另一方面,你不必手动分配和释放内存,这是一种解脱(我做了很多C和Python编程,所以我看到了好处)。
第三,在Python中有很多内存分配和释放。根据Python的构建方式以及分配内存的底层操作系统策略,可能会发生任何数量的事情,导致地址不会按顺序增加。但由于所有都是一个对象,因此所有内容都会发生基础分配。
我有这个疑问,因为我首先学习了C ++(说实话,Turbo C ++)和字符串&#39; Python中定义的地址与C ++中的地址有很大不同。我想这在Python中没问题,因为我们无法通过Python中的地址访问对象,我是对的吗?
是的,不。当你说c[0]
时,在引擎盖下面会运行一个特殊的方法来从字符串中检索子字符串。这与您在C ++中获得的不同。但是,Python确实有效地将字符串存储在引擎盖下作为字节序列。因为你无法看到效率检查地址,它并不意味着它不在那里。另外,正如我上面提到的,c[0]
返回一个新字符串,表示您想要的子字符串。 Python在这里很聪明,它将返回一个1个字符的字符串,但它将是一个实习生的字符串。您可以看到某些字母具有相同的地址:
c[0]
您可以看到>>> for c in "hobo":
... print c, id(c)
...
h 4434994600
o 4434861432
b 4434859712
o 4434861432
的字符串共享相同的地址 - BTW,示例是Python 2,但Python 3中存在相同的质量。
你是对的,你不能通过它的地址访问对象 - 至少那不是语言的一个特征。如何生成id是一个实现细节,但您应该依靠每个Python解释器这样做。
另外,为c和c [0]设置不同的地址有什么意义?对于某些人来说,这些问题可能是不必要的,但我很想知道Python如何将地址分配给各种数据类型,特别是(此处)字符串。
我在上面解释了这一点,但回顾一下:"o"
和c
与C不同。在Python中,第一个是字符串,第二个是请求包含第一个字符的子字符串字符串。
Python确实在许多领域使用了竞技场式的内存管理方案,但在大多数情况下,你并不需要关心它。如果您有点好奇,我建议您查看Python source code。 c[0]
子目录具有许多语言和低级运行时支持位。并且还意识到Python也预先缓存了一些东西,这也可以解释你在上面看到的地址差异。