• 全部
  • 互动交流
  • 文章分享

python字符串地址问题

nowayyyyy what? 2020-11-15 05:57:01
python小白一枚问一个我比较在意的问题。我在python3.8.2里查看字符串代码是这样子的结果
>>> id('cpccp')
4300388336
>>> id('oee8ed.')
4300388336
但是在3.7里不是这样了
id('cpccp')
4368612352
id('oee8ed')
4370164792
为什么在3.8里面不同的字符串地址一样,而在3.7里面地址会不一样,请问有大神能够帮忙解决吗,好像到处也没人问这个问题的,我就来这里看看。
但是好像也有一样的点,如下>>> a='apple'
>>> b='basket'
>>> a+b is 'applebasket'#不管是a+b还是a+'basket'都是false
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
False
>>> id(a+b)
4300389360
>>> id('apple'+b)#输出地址都一样
4300389360
>>> id('apple'+'basket')
4300389360
=================================================
a='apple'#python3.7
b='basket'
a+b is 'applebasket'
False
id(a+b)
4369049264#和下面的地址不一样
id(a+'basket')
4366530480


如上,如能解决万分感谢
...全文
277 点赞 收藏 8
写回复
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
nowayyyyy 02-07
引用 7 楼 cclxpp123 的回复:
python底层通过引用计数机制来管理对象, 例如
a = 'xxx'
b = a
相当于给字符串对象贴了两个标签, 也就是两个引用. 一旦对象引用数变为0, 则对象被销毁(这让我想到了皮克斯的一部动画: 如果没有人能记得你, 则你才真正的死了). id函数给出一个活着的对象的内存地址, 因此同一时刻的两个对象内存地址一定不同, 但不同时刻可以相同, 因为新对象可以占据已死亡对象的那个位置. 可以用
from _ctypes import PyObj_FromPtr
函数来进行反向id操作, 即从一个id值来获得对象. 例如
a = 'xxx'

id(a)
Out[32]: 1713993701936

PyObj_FromPtr(1713993701936)
Out[33]: 'xxx'
但如果运行下面代码
id('yyy')
Out[34]: 1714093600944

PyObj_FromPtr(1714093600944)
则会导致内核崩溃. 原因在于字符串'yyy'这个对象的引用为0, 计算完id就销毁, 因此下面再访问这个非法地址会导致内核崩溃.
非常感谢 很专业的回答
回复
cclxpp123 01-13
python底层通过引用计数机制来管理对象, 例如
a = 'xxx'
b = a
相当于给字符串对象贴了两个标签, 也就是两个引用. 一旦对象引用数变为0, 则对象被销毁(这让我想到了皮克斯的一部动画: 如果没有人能记得你, 则你才真正的死了). id函数给出一个活着的对象的内存地址, 因此同一时刻的两个对象内存地址一定不同, 但不同时刻可以相同, 因为新对象可以占据已死亡对象的那个位置. 可以用
from _ctypes import PyObj_FromPtr
函数来进行反向id操作, 即从一个id值来获得对象. 例如
a = 'xxx'

id(a)
Out[32]: 1713993701936

PyObj_FromPtr(1713993701936)
Out[33]: 'xxx'
但如果运行下面代码
id('yyy')
Out[34]: 1714093600944

PyObj_FromPtr(1714093600944)
则会导致内核崩溃. 原因在于字符串'yyy'这个对象的引用为0, 计算完id就销毁, 因此下面再访问这个非法地址会导致内核崩溃.
回复
nowayyyyy 01-13
谢谢快乐的小猪我现在已经明白不少了
回复
欢乐的小猪 2020-11-21
编译就是编译器帮你把源代码翻译成机器能识别的代码 .(当然只是一般意义上这么说,实际上可能只是翻译成某个中间状态的语言.比如 Java 只有JVM识别的字节码,C#中只有CLR能识别的MSIL.另外还有啥链接器.汇编器.为了了便于理解我们可以统称为编译器) 运行时就是代码跑起来了.被装载到内存中去了 .(你的代码保存在磁盘上没装入内存之前是个死家伙.只有跑到内存中才变成活的).
回复
nowayyyyy 2020-11-20
引用 3 楼 欢乐的小猪 的回复:
python中的驻留发生在compile_time,而不是run_time。 为什么会出现这种情况? 不都只是包含字母吗,应该被主动intern的啊? 这是由于在第一个例子中,‘op’ + ‘q’是在compile-time(编译时)求值的,被替换成了’opq’,而在第二个例子中,c + ‘q’是在run-time(运行时)拼接的,导致没有被主动intern。
谢谢你两个帖子都回了,但是就是这个为啥是变量就是运行时不清楚有点懵。。。
回复
欢乐的小猪 2020-11-19
python中的驻留发生在compile_time,而不是run_time。 为什么会出现这种情况? 不都只是包含字母吗,应该被主动intern的啊? 这是由于在第一个例子中,‘op’ + ‘q’是在compile-time(编译时)求值的,被替换成了’opq’,而在第二个例子中,c + ‘q’是在run-time(运行时)拼接的,导致没有被主动intern。
回复
nowayyyyy 2020-11-18
我好像重复发帖了。。。那边有人说是共享内存的问题,每个系统和电脑不一样。python好想有个intern机制那为啥你的这个地址一样呢,是不是版本不一样不一定有intern机制啊。还有就是我第二个问题是关于编译期和运行期的,当时没讲清楚,一个变量和一个字符串在is前面比较后面的字符串的地址问题,因为有intern机制,我也是在python中的特权种族这篇博客里看到的,当时很不理解因为讲的很不清晰。
回复
rrrr336 2020-11-15
首先,python的 id 函数 和 C语言中的 取地址操作 & 类似,但也有些不同: C语言 的 & 操作是真实取得一个内存地址或者虚拟页面内存的地址,返回的是地址值,是有真实地址对应的。 而 python 的 id() 函数只是分配给每一个对象的唯一的一个固定不变的整数值。 看官方文档: “ id(object) : Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value." ---- 引自 python.org 就是说得到的并不是一个地址,而是一个唯一的固定的整数值. 而且: 两个不同的没有重叠的生命周期的对象 (two objects with non-overlapping lifetimes ) 可能有 同样的 id值( may have the same id() value) 1. 这就解释了 你的第一个问题: 在命令行下, id('abcd') 后又运行 id('123') 可能有同一个值,因为第一个值的生命周期已经结束,然后再启动的第二个值,所以id可以相同啊。 可以形象地理解为: 在黑板某一个位置写了一行字,擦掉后再在同一个位置写另外的字,位置相同字不同,是一个道理。 至于 版本问题,3.8, 3.7的不同,只是不同版本编译系统的差异,不影响对 id() 函数的定义。 2. python中有一个重要概念: 字符串是固定的,不能更改的。这和C语言是不同的。 所以: python中,如果两个字符串相同,他们可以有同一个id (python先查有没有相同的字符串,有就用现成的),也可以不同 而不同的字符串,他们一定有不同的id >>> x = 'abcd' >>> y = '123' >>> z = 'abcd' >>> id(x) 69937312 >>> id(z) 69937312 >>> id(y) 69937408 这解释了你的第二个问题。 当然,版本不同,编译可能略有差别。 个人拙见,参考
回复
相关推荐
发帖
脚本语言
创建于2007-08-27

3.7w+

社区成员

JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
申请成为版主
帖子事件
创建了帖子
2020-11-15 05:57
社区公告

CSDN 脚本语言社区接受专栏投稿(专栏会在顶部创建专属你的栏目),投稿需满足以下要求:

  • 脚本语言技术相关;
  • 文章持续更新,保持活跃;
  • 内容清晰明了,干货为主;
  • 文章排版有序,有条有理。

本社区开通招聘专栏,发布招聘信息请联系版主,发布者需要保证招聘信息真实有效,CSDN 平台和版主不对招聘内容负责!

联系方式:私聊版主、发送邮件、QQ联系等均可: