P. *_*tiz 11 python string python-internals
我完全坚持这个
>>> s = chr(8263)
>>> x = s[0]
>>> x is s[0]
False
Run Code Online (Sandbox Code Playgroud)
这怎么可能?这是否意味着通过索引访问字符串字符会创建相同字符的新实例?我们来试验:
>>> L = [s[0] for _ in range(1000)]
>>> len(set(L))
1
>>> ids = map(id, L)
>>> len(set(ids))
1000
>>>
Run Code Online (Sandbox Code Playgroud)
哎呀浪费字节;)或者它是否意味着str.__getitem__有一个隐藏的功能?有人可以解释一下吗?
但这并不是我的惊喜:
>>> s = chr(8263)
>>> t = s
>>> print(t is s, id(t) == id(s))
True True
Run Code Online (Sandbox Code Playgroud)
这很清楚:t是别名s,所以它们代表相同的对象和身份重合.但同样,以下是可能的:
>>> print(t[0] is s[0])
False
Run Code Online (Sandbox Code Playgroud)
s并且t是同一个对象那又怎样?
但更糟糕的是
>>> print(id(t[0]) == id(s[0]))
True
Run Code Online (Sandbox Code Playgroud)
t[0]并且s[0]没有被垃圾收集,被is运营商视为同一个对象但具有不同的ID?有人可以解释一下吗?
这里有两点要做.
首先,Python确实通过调用创建了一个新字符__getitem__,但前提是该字符的序数值大于 256.
例如:
>>> s = chr(256)
>>> s[0] is s
True
>>> t = chr(257)
>>> t[0] is t
False
Run Code Online (Sandbox Code Playgroud)
这是因为在内部,编译的getitem函数检查单个字符的序数值,并调用get_latin1_charif值为256或更小.这允许共享一些单字符串.否则,将创建一个新的unicode对象.
第二个问题涉及垃圾收集,并显示解释器可以非常快速地重用内存地址.当你写:
>>> s = t # = chr(257)
>>> t[0] is s[0]
False
Run Code Online (Sandbox Code Playgroud)
Python首先创建两个新的单字符串,然后比较它们的内存地址.它们具有不同的地址(根据上面的解释,我们有不同的对象),因此将对象与is返回False 进行比较.
另一方面,我们可以看到一个看似矛盾的情况:
>>> id(t[0]) == id(s[0])
True
Run Code Online (Sandbox Code Playgroud)
但这是因为解释器很快就会重新使用t[0]它s[0]在以后创建新字符串时的内存地址.
如果你检查这一行产生的字节码(例如,dis见 - 见下文),你会看到每一面的地址是一个接一个地分配的(创建一个新的字符串对象,然后id在其上调用).
返回后对对象的引用将t[0]降为零id(t[0])(我们现在对整数进行比较,而不是对象本身).这意味着s[0]可以在以后创建时重用相同的内存地址.
这是id(t[0]) == id(s[0])我注释的行的反汇编字节码.
您可以看到创建t[0]之前的生命周期s[0](没有对它的引用),因此可以重用其内存.
2 0 LOAD_GLOBAL 0 (id)
3 LOAD_GLOBAL 1 (t)
6 LOAD_CONST 1 (0)
9 BINARY_SUBSCR # t[0] is created
10 CALL_FUNCTION 1 # id(t[0]) is computed...
# ...lifetime of string t[0] over
13 LOAD_GLOBAL 0 (id)
16 LOAD_GLOBAL 2 (s)
19 LOAD_CONST 1 (0)
22 BINARY_SUBSCR # s[0] is created...
# ...free to reuse t[0] memory
23 CALL_FUNCTION 1 # id(s[0]) is computed
26 COMPARE_OP 2 (==) # the two ids are compared
29 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
413 次 |
| 最近记录: |