In [243]: s1 = '\xe4\xb9\xa0\xe6\x83\xaf'
In [244]: s2 = u'\xe4\xb9\xa0\xe6\x83\xaf'
In [245]: len(s1)
Out[245]: 6
In [246]: len(s2)
Out[246]: 6
In [247]: s1.__sizeof__()
Out[247]: 43
In [248]: s2.__sizeof__()
Out[248]: 76
s1 的数据类型为 str , s2 的数据类型为 unicode ,其中两个数据的 len 是相同的,但是其所占用的 bytes(字节数)是怎么算的呢?
1
pixstone 2016-08-02 13:37:22 +08:00
len 是是返回 char 的数量
sizeof 是返回占用空间,比如 utf - 8 编码下的 占用空间多, 假如 "a" 在 ascii 中占一位,那么 “续” 在 unicode 就占 2 位了, 但 len 都是 1 。具体 utf - 8 和 ascii 具体占几位 我忘记了。。 |
3
GeekGao 2016-08-02 14:25:36 +08:00
__sizeof__是 2.6+版本支持的,但不作为生产环境用途, 与之相关功能说明请参考文档中的: sys.getsizeof ,它不是用来计算 string 长度的!
|
4
justou 2016-08-02 14:42:05 +08:00 2
sizeof 计算的是那个对象占用的空间(跟 C 语言的 sizeof 类似), 而 str, unicode 在底层都是一个 C 结构体表示的, 所以这样算出来的字节数是整个结构体的字节数(包括里面字符指针的内存大小)
如果要获得里面字符字节数, 需要直接访问里面的 buffer 信息 from array import array s1 = '\xe4\xb9\xa0\xe6\x83\xaf' s2 = u'\xe4\xb9\xa0\xe6\x83\xaf' arr = array('c', s1) print arr.buffer_info()[1] * arr.itemsize uarr = array('u', s2) print uarr.buffer_info()[1] * uarr.itemsize |
6
justou 2016-08-02 14:50:57 +08:00
另外, 也可以这样来测试
In [1]: ''.__sizeof__() Out[1]: 21 In [2]: '1'.__sizeof__() Out[2]: 22 In [3]: '123'.__sizeof__() Out[3]: 24 In [4]: u''.__sizeof__() Out[4]: 26 In [5]: u'1'.__sizeof__() Out[5]: 28 创建一个空对象来看这个对象对应结构体的大小, 然后慢慢加字符进去看大小之差 |
7
GeekGao 2016-08-02 14:52:19 +08:00
@xinali 你没看懂我意思么,意思就是说你这么算 unicode 长度是不对的, len 和__sizeof__ 不是一个概念。
|
8
ovear 2016-08-02 14:53:55 +08:00
https://zh.wikipedia.org/zh/UTF-8 utf8 是变长的。。
|
12
mulog 2016-08-02 15:23:32 +08:00
python 的 str 又不是只存字符串本身。。
```C typedef struct { PyObject_VAR_HEAD long ob_shash; int ob_sstate; char ob_sval[1]; } PyStringObject; ``` 具体怎么算我也不知道,我猜是 16 + 8 + 4 + 8 + len(your_str) + 1 unicode 同理,有兴趣去看代码嘛。。 |
13
yangtukun1412 2016-08-02 15:27:03 +08:00 1
64 位默认情况下, PyStringObject 结构体占用 37 字节, 每增加一个字符就多一个 char 的 size.
PyUnicodeObject 结构体占用 48 字节, 每增加一个字符就多一个 Py_UNICODE_TYPE 的 size, 这个值是在编译时根据 Py_UNICODE_SIZE 指定的, 默认 ucs2 的情况下应该是 unsigned short, 2 字节. 值得注意的是, unicode 在计算 size 的时候多加了 1 位: sizeof(Py_UNICODE) * (v->length + 1), 因此 sys.getsizeof(u'') == 50. |
14
GeekGao 2016-08-02 15:35:59 +08:00 1
看了下代码,关于这个__sizeof__方法不同对象提供的方法不同,其中你要的 stringobject 的实现:
static PyObject * string_sizeof(PyStringObject *v) { Py_ssize_t res; res = PyStringObject_SIZE + v->ob_size * v->ob_type->tp_itemsize; return PyInt_FromSsize_t(res); } 其中 v->ob_size 是实际长度( byte ), PyStringObject_SIZE 相当于 sizeof(PyStringObject), tp_itemsize 为 sizeof(char) 代码版本: CPython 2.7.x |
15
GeekGao 2016-08-02 16:06:16 +08:00
unicodeobject 对应实现为:
static PyObject * unicode__sizeof__(PyUnicodeObject *v) { return PyInt_FromSsize_t(sizeof(PyUnicodeObject) + sizeof(Py_UNICODE) * (v->length + 1)); } |
16
shuax 2016-08-02 18:06:50 +08:00
sizeof 的意思是我实现这个东西的时候花了多少内存,和 len 没有什么好比较的。
|