Quantcast

[CPyUG:101897] 关于Python中String的Intern机制

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[CPyUG:101897] 关于Python中String的Intern机制

Xunzhen Quan
最近我在读《Python源码剖析》一书,觉得写的很好,很推荐比较懂Python而又会一些C的人看。

但我在看着本书的时候,产生了一个疑问,这个疑问是我在看关于Python的Dict对象实现当中看到的,Dict对象对于散列表搜索链中被删除的对象
采用了一个标准的Python字符串对象“<dummy key>”作为key来识别,而且在后续的判断中都仅直接判断key是否为这个对像。因此我想
到,是否可以构造一个同样为“<dummy key>”的字符串,利用Intern分享机制扰乱Dict对象的处理。结果不用想,自然是失败了。修改
Python源代码编译观察发现自己创建的那个字符串永远也不会指向那个dummy,于是我就开始转而研究Python的Intern机制。

在考察了stringobject.c中的代码后,我发现FromString和FromStringAndSize都是不会为长字符串(长度超过1的
字符串)调用Intern机制的,因此我很怀疑Python内部是否有真正的利用Intern机制。于是在Ubuntu自带Python的交互模式下进
行了如下实验:
a = 'aaa'
b = 'aaa
print id(a), id(b)
a = '<aaa'
b = '<aaa'
print id(a), id(b)
结果发现第一处输出的两个数是一样的,证明其中肯定调用了Intern机制;但第二处输出却完全不同。我猜想应该是其自动探测如果第一个字符为“<”就
不进行Intern。

随后我在.py文件中输入同样代码,发现每次的输出的结果中两项相同,甚至加入“<dummy key>”都是,怀疑是编译时进行了Intern。

以上是我进行的探究……那么我现在十分好奇Python在代码中的什么位置通过什么方式对长字符串进行了Intern,又是在代码中的什么位置通过什么
方式阻止了外部“<dummy key>”字符串可能照成的扰乱行为?求解答
--~--~---------~--~----~------------~-------~--~----~
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:[hidden email]
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[CPyUG:101907] Re: 关于Python中String的Intern机制

Xunzhen Quan
没人理我么……那本书的作者不是也因该在这儿么……

On 9月26日, 下午2时23分, upsuper <[hidden email]> wrote:

> 最近我在读《Python源码剖析》一书,觉得写的很好,很推荐比较懂Python而又会一些C的人看。
>
> 但我在看着本书的时候,产生了一个疑问,这个疑问是我在看关于Python的Dict对象实现当中看到的,Dict对象对于散列表搜索链中被删除的对象
> 采用了一个标准的Python字符串对象“<dummy key>”作为key来识别,而且在后续的判断中都仅直接判断key是否为这个对像。因此我想
> 到,是否可以构造一个同样为“<dummy key>”的字符串,利用Intern分享机制扰乱Dict对象的处理。结果不用想,自然是失败了。修改
> Python源代码编译观察发现自己创建的那个字符串永远也不会指向那个dummy,于是我就开始转而研究Python的Intern机制。
>
> 在考察了stringobject.c中的代码后,我发现FromString和FromStringAndSize都是不会为长字符串(长度超过1的
> 字符串)调用Intern机制的,因此我很怀疑Python内部是否有真正的利用Intern机制。于是在Ubuntu自带Python的交互模式下进
> 行了如下实验:
> a = 'aaa'
> b = 'aaa
> print id(a), id(b)
> a = '<aaa'
> b = '<aaa'
> print id(a), id(b)
> 结果发现第一处输出的两个数是一样的,证明其中肯定调用了Intern机制;但第二处输出却完全不同。我猜想应该是其自动探测如果第一个字符为“<”就
> 不进行Intern。
>
> 随后我在.py文件中输入同样代码,发现每次的输出的结果中两项相同,甚至加入“<dummy key>”都是,怀疑是编译时进行了Intern。
>
> 以上是我进行的探究……那么我现在十分好奇Python在代码中的什么位置通过什么方式对长字符串进行了Intern,又是在代码中的什么位置通过什么
> 方式阻止了外部“<dummy key>”字符串可能照成的扰乱行为?求解答
--~--~---------~--~----~------------~-------~--~----~
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:[hidden email]
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[CPyUG:/] Re: 关于Python中String的Intern机制

limodou
2009/9/26 upsuper <[hidden email]>:
> 没人理我么……那本书的作者不是也因该在这儿么……
>

估计真正看过的人并不多,作者也不能保证24在列表里呆着啊。

--
I like python!
UliPad <<The Python Editor>>: http://code.google.com/p/ulipad/
UliWeb <<simple web framework>>: http://uliwebproject.appspot.com
My Blog: http://hi.baidu.com/limodou

--~--~---------~--~----~------------~-------~--~----~
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:[hidden email]
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[CPyUG:101909] Re: [CPyUG:/] Re: 关于Python中String的Intern机制

ubunoon-2
估计很多人是有心使不上力,这里面深入看Python源代码的人很少,我不知道应该怎么说才好,都是市场应用导向的需求。

2009/9/26 limodou <[hidden email]>
2009/9/26 upsuper <[hidden email]>:
> 没人理我么……那本书的作者不是也因该在这儿么……
>

估计真正看过的人并不多,作者也不能保证24在列表里呆着啊。

--
I like python!
UliPad <<The Python Editor>>: http://code.google.com/p/ulipad/
UliWeb <<simple web framework>>: http://uliwebproject.appspot.com
My Blog: http://hi.baidu.com/limodou





--
To be pythoner
My blog: http://www.cnblogs.com/ubunoon/


--~--~---------~--~----~------------~-------~--~----~
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:[hidden email]
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[CPyUG:101911] Re: 关于Python中String的Intern机制

heroboy
In reply to this post by Xunzhen Quan
dictobject.c :

    for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
        i = (i << 2) + i + perturb + 1;
        ep = &ep0[i & mask];
        if (ep->me_key == NULL)
            return freeslot == NULL ? ep : freeslot;
        if (ep->me_key == key
            || (ep->me_hash == hash
                && ep->me_key != dummy
            && _PyString_Eq(ep->me_key, key)))
            return ep;
        if (ep->me_key == dummy && freeslot == NULL)
            freeslot = ep;
    }

红色这一行说明了,"<dummy key>"不会扰乱dict的机制。而且,由于dummy在被创建的时候没有被intern,所以dummy指针地址不会和其他的"<dummy key>"的地址相同。
另外我全局查找了一下PyString_InternInPlace,只有在key都是string的dict和编译代码,还有marshal的时候intern。
我在控制台里面输入:
a = {'<abc':1}
b = {'<abc':2}
print map(id,a.keys()),map(id,b.keys())
输出不同的id(如果换成'abc'则输出一样的id。貌似只要是非法变量名的字符串都输出不同的id)

而运行下面的代码:
s = raw_input('input:')
d1 = {s:1}
d2 = {s:2}
print map(id,d1.keys()),map(id,d2.keys())
输入:<abc,则输出一样的id
这我就不知道为什么了。

2009/9/26 upsuper <[hidden email]>
最近我在读《Python源码剖析》一书,觉得写的很好,很推荐比较懂Python而又会一些C的人看。

但我在看着本书的时候,产生了一个疑问,这个疑问是我在看关于Python的Dict对象实现当中看到的,Dict对象对于散列表搜索链中被删除的对象
采用了一个标准的Python字符串对象“<dummy key>”作为key来识别,而且在后续的判断中都仅直接判断key是否为这个对像。因此我想
到,是否可以构造一个同样为“<dummy key>”的字符串,利用Intern分享机制扰乱Dict对象的处理。结果不用想,自然是失败了。修改
Python源代码编译观察发现自己创建的那个字符串永远也不会指向那个dummy,于是我就开始转而研究Python的Intern机制。

在考察了stringobject.c中的代码后,我发现FromString和FromStringAndSize都是不会为长字符串(长度超过1的
字符串)调用Intern机制的,因此我很怀疑Python内部是否有真正的利用Intern机制。于是在Ubuntu自带Python的交互模式下进
行了如下实验:
a = 'aaa'
b = 'aaa
print id(a), id(b)
a = '<aaa'
b = '<aaa'
print id(a), id(b)
结果发现第一处输出的两个数是一样的,证明其中肯定调用了Intern机制;但第二处输出却完全不同。我猜想应该是其自动探测如果第一个字符为“<”就
不进行Intern。

随后我在.py文件中输入同样代码,发现每次的输出的结果中两项相同,甚至加入“<dummy key>”都是,怀疑是编译时进行了Intern。

以上是我进行的探究……那么我现在十分好奇Python在代码中的什么位置通过什么方式对长字符串进行了Intern,又是在代码中的什么位置通过什么
方式阻止了外部“<dummy key>”字符串可能照成的扰乱行为?求解答



--~--~---------~--~----~------------~-------~--~----~
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:[hidden email]
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[CPyUG:101916] Re: 关于Python中String的Intern机制

Xunzhen Quan
In reply to this post by limodou
这我明白......不过很希望能尽快得到一个解释来着......

On Sep 26, 7:11 pm, limodou <[hidden email]> wrote:

> 2009/9/26 upsuper <[hidden email]>:
>
> > 没人理我么......那本书的作者不是也因该在这儿么......
>
> 估计真正看过的人并不多,作者也不能保证24在列表里呆着啊。
>
> --
> I like python!
> UliPad <<The Python Editor>>:http://code.google.com/p/ulipad/
> UliWeb <<simple web framework>>:http://uliwebproject.appspot.com
> My Blog:http://hi.baidu.com/limodou
--~--~---------~--~----~------------~-------~--~----~
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:[hidden email]
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[CPyUG:101917] Re: 关于Python中String的Intern机制

Xunzhen Quan
In reply to this post by heroboy
"红色这一行"?颜色没显示出来的说......
话说intern的触发机制似乎很有趣,而且如果按照代码的话,在外部库中调用FromString或FromStringAndSize创建的str
就永远也不会被intern了咯?而且根据代码似乎创建时也没有检查是否intern......满诡异的说......

On Sep 26, 8:21 pm, Heroboy <[hidden email]> wrote:

> dictobject.c :
>
>     for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
>         i = (i << 2) + i + perturb + 1;
>         ep = &ep0[i & mask];
>         if (ep->me_key == NULL)
>             return freeslot == NULL ? ep : freeslot;
>         if (ep->me_key == key
>             || (ep->me_hash == hash
>                 && ep->me_key != dummy
>             && _PyString_Eq(ep->me_key, key)))
>             return ep;
>         if (ep->me_key == dummy && freeslot == NULL)
>             freeslot = ep;
>     }
>
> 红色这一行说明了,"<dummy
> key>"不会扰乱dict的机制。而且,由于dummy在被创建的时候没有被intern,所以dummy指针地址不会和其他的"<dummy
> key>"的地址相同。
> 另外我全局查找了一下PyString_InternInPlace,只有在key都是string的dict和编译代码,还有marshal的时候intern。
> 我在控制台里面输入:
> a = {'<abc':1}
> b = {'<abc':2}
> print map(id,a.keys()),map(id,b.keys())
> 输出不同的id(如果换成'abc'则输出一样的id。貌似只要是非法变量名的字符串都输出不同的id)
>
> 而运行下面的代码:
> s = raw_input('input:')
> d1 = {s:1}
> d2 = {s:2}
> print map(id,d1.keys()),map(id,d2.keys())
> 输入:<abc,则输出一样的id
> 这我就不知道为什么了。
>
> 2009/9/26 upsuper <[hidden email]>
>
> > 最近我在读《Python源码剖析》一书,觉得写的很好,很推荐比较懂Python而又会一些C的人看。
>
> > 但我在看着本书的时候,产生了一个疑问,这个疑问是我在看关于Python的Dict对象实现当中看到的,Dict对象对于散列表搜索链中被删除的对象
> > 采用了一个标准的Python字符串对象"<dummy key>"作为key来识别,而且在后续的判断中都仅直接判断key是否为这个对像。因此我想
> > 到,是否可以构造一个同样为"<dummy key>"的字符串,利用Intern分享机制扰乱Dict对象的处理。结果不用想,自然是失败了。修改
> > Python源代码编译观察发现自己创建的那个字符串永远也不会指向那个dummy,于是我就开始转而研究Python的Intern机制。
>
> > 在考察了stringobject.c中的代码后,我发现FromString和FromStringAndSize都是不会为长字符串(长度超过1的
> > 字符串)调用Intern机制的,因此我很怀疑Python内部是否有真正的利用Intern机制。于是在Ubuntu自带Python的交互模式下进
> > 行了如下实验:
> > a = 'aaa'
> > b = 'aaa
> > print id(a), id(b)
> > a = '<aaa'
> > b = '<aaa'
> > print id(a), id(b)
> > 结果发现第一处输出的两个数是一样的,证明其中肯定调用了Intern机制;但第二处输出却完全不同。我猜想应该是其自动探测如果第一个字符为"<"就
> > 不进行Intern。
>
> > 随后我在.py文件中输入同样代码,发现每次的输出的结果中两项相同,甚至加入"<dummy key>"都是,怀疑是编译时进行了Intern。
>
> > 以上是我进行的探究......那么我现在十分好奇Python在代码中的什么位置通过什么方式对长字符串进行了Intern,又是在代码中的什么位置通过什么
> > 方式阻止了外部"<dummy key>"字符串可能照成的扰乱行为?求解答
>
>
--~--~---------~--~----~------------~-------~--~----~
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:[hidden email]
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[CPyUG:101920] Re: 关于Python中String的Intern机制

heroboy


2009/9/26 upsuper <[hidden email]>
"红色这一行"?颜色没显示出来的说......
话说intern的触发机制似乎很有趣,而且如果按照代码的话,在外部库中调用FromString或FromStringAndSize创建的str
就永远也不会被intern了咯?而且根据代码似乎创建时也没有检查是否intern......满诡异的说......

不就是这一行: && ep->me_key != dummy
并不需要每个string都被intern,只需要会被多次引用或者需要快速查找的地方用intern,否则那个intern的dict岂不是越来越大。
On Sep 26, 8:21 pm, Heroboy <[hidden email]> wrote:
> dictobject.c :
>
>     for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
>         i = (i << 2) + i + perturb + 1;
>         ep = &ep0[i & mask];
>         if (ep->me_key == NULL)
>             return freeslot == NULL ? ep : freeslot;
>         if (ep->me_key == key
>             || (ep->me_hash == hash
>                 && ep->me_key != dummy
>             && _PyString_Eq(ep->me_key, key)))
>             return ep;
>         if (ep->me_key == dummy && freeslot == NULL)
>             freeslot = ep;
>     }
>
> 红色这一行说明了,"<dummy
> key>"不会扰乱dict的机制。而且,由于dummy在被创建的时候没有被intern,所以dummy指针地址不会和其他的"<dummy
> key>"的地址相同。
> 另外我全局查找了一下PyString_InternInPlace,只有在key都是string的dict和编译代码,还有marshal的时候intern。
> 我在控制台里面输入:
> a = {'<abc':1}
> b = {'<abc':2}
> print map(id,a.keys()),map(id,b.keys())
> 输出不同的id(如果换成'abc'则输出一样的id。貌似只要是非法变量名的字符串都输出不同的id)
>
> 而运行下面的代码:
> s = raw_input('input:')
> d1 = {s:1}
> d2 = {s:2}
> print map(id,d1.keys()),map(id,d2.keys())
> 输入:<abc,则输出一样的id
> 这我就不知道为什么了。
>
> 2009/9/26 upsuper <[hidden email]>
>
> > 最近我在读《Python源码剖析》一书,觉得写的很好,很推荐比较懂Python而又会一些C的人看。
>
> > 但我在看着本书的时候,产生了一个疑问,这个疑问是我在看关于Python的Dict对象实现当中看到的,Dict对象对于散列表搜索链中被删除的对象
> > 采用了一个标准的Python字符串对象"<dummy key>"作为key来识别,而且在后续的判断中都仅直接判断key是否为这个对像。因此我想
> > 到,是否可以构造一个同样为"<dummy key>"的字符串,利用Intern分享机制扰乱Dict对象的处理。结果不用想,自然是失败了。修改
> > Python源代码编译观察发现自己创建的那个字符串永远也不会指向那个dummy,于是我就开始转而研究Python的Intern机制。
>
> > 在考察了stringobject.c中的代码后,我发现FromString和FromStringAndSize都是不会为长字符串(长度超过1的
> > 字符串)调用Intern机制的,因此我很怀疑Python内部是否有真正的利用Intern机制。于是在Ubuntu自带Python的交互模式下进
> > 行了如下实验:
> > a = 'aaa'
> > b = 'aaa
> > print id(a), id(b)
> > a = '<aaa'
> > b = '<aaa'
> > print id(a), id(b)
> > 结果发现第一处输出的两个数是一样的,证明其中肯定调用了Intern机制;但第二处输出却完全不同。我猜想应该是其自动探测如果第一个字符为"<"就
> > 不进行Intern。
>
> > 随后我在.py文件中输入同样代码,发现每次的输出的结果中两项相同,甚至加入"<dummy key>"都是,怀疑是编译时进行了Intern。
>
> > 以上是我进行的探究......那么我现在十分好奇Python在代码中的什么位置通过什么方式对长字符串进行了Intern,又是在代码中的什么位置通过什么
> > 方式阻止了外部"<dummy key>"字符串可能照成的扰乱行为?求解答
>
>



--~--~---------~--~----~------------~-------~--~----~
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:[hidden email]
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [CPyUG:101897] 关于Python中String的Intern机制

Elems
This post has NOT been accepted by the mailing list yet.
In reply to this post by Xunzhen Quan
长字符串这个什么时候被intern,还是很疑惑啊,没搞懂啊
Loading...