假设我在Python中有一个字符串my_string
,并根据some_pattern
对其进行标记:
match.re.search(some_pattern, my_string)
string_1 = match.group(1)
string_2 = match.group(2)
....
string_1
中的子串的string_2
和my_string
(“深”)副本或内存中相同位置的引用是什么? string_1
和string_2
为my_string
中的字符的完整副本分配内存吗?
请注意,我没有询问字符串的不变性。如果my_string
很长,我想知道我通过标记字符串来获取内存中的内容。
我不需要确切地知道重复使用了多少内存,但知道字符串的标记化是否最终会重复内存肯定会有用。
答案 0 :(得分:3)
从查看Python 2.7.3源代码,获取字符串片段可以复制字符数据:
Objects/stringobject.c
:
string_slice()
调用以下函数PyString_FromStringAndSize()
:
/* Inline PyObject_NewVar */
op = (PyStringObject *)PyObject_MALLOC(PyStringObject_SIZE + size);
if (op == NULL)
return PyErr_NoMemory();
PyObject_INIT_VAR(op, &PyString_Type, size);
op->ob_shash = -1;
op->ob_sstate = SSTATE_NOT_INTERNED;
if (str != NULL)
Py_MEMCPY(op->ob_sval, str, size);
op->ob_sval[size] = '\0';
这里,str
是指向字符数据的指针,size
是长度。注意malloc和memcpy。
不同的Python实现(实际上不同版本的CPython)可能表现不同。例如,Jython可能使用java.lang.String
,它不会复制。
答案 1 :(得分:1)
字符串在python中是不可变的,因此子字符串只是新对象。
In [7]: str="foobar"
In [8]: id(str)
Out[8]: 140976032
In [10]: id(str[:4])
Out[10]: 141060224
返回的子串对象与原始字符串对象相同的唯一情况是string==substring
:
In [16]: foo="foobar"
In [17]: id(foo)
Out[17]: 140976032
In [18]: id(foo[:])
Out[18]: 140976032
In [19]: foo="foobar"*10000 # huge string
In [20]: id(foo)
Out[20]: 141606344
In [21]: id(foo[:])
Out[21]: 141606344
答案 2 :(得分:1)
Python字符串是不可变的,因此在这种情况下区别并不是那么有意义,但它们是副本。您无法对string_1
和string_2
执行任何操作会影响my_string
的内容。
答案 3 :(得分:0)
不确定它有多大帮助甚至可以回答您的问题,但您可以使用finditer
然后仅根据需要对原始字符串进行切片...
>>> import re
>>> string = 'abcdefhijkl'
>>> matches = list(re.finditer('.' , string))
>>> dir(matches[0])
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'end', 'endpos', 'expand', 'group', 'groupdict', 'groups', 'lastgroup', 'lastindex', 'pos', 're', 'regs', 'span', 'start', 'string']
>>> matches[0].span()
(0, 1)
然后从那里开始......