【问题标题】:sizeof(string) not equal to string lengthsizeof(string) 不等于字符串长度
【发布时间】:2016-08-03 16:30:05
【问题描述】:

我曾经认为每个字符都是一个字节(至少在 c/c++ 中是这样)所以字符串的大小应该等于len(string) 字节。然而,一个简单的实验告诉我,在python中并非如此:

import string, sys, random
# abstracted code, removed unnecessary parts
def loadKeyLength(db,key,N):
    val = key[:5] + ''.join(random.choice(string.ascii_letters + string.digits) for _ in xrange(N-5))
    print sys.getsizeof(val), len(val),val

def loadKeysSize(s): 
    r=0
    key=str(s).zfill(5)+str(r).zfill(5)
    loadKeyLength(None,key,s)

for i in range(80,120,3):
    loadKeysSize(i)

在 Ubuntu 14.04 上的输出:

117 80 000802qdxV2TY3qjGpe6F35hLczQNE2h7bWRWpHEMxqcyrb01sI2A6gcTLKLxdQSFjGMFtWPZJDOtKe4
120 83 00083oX6FouwlAyUkmZZCLWuIWnDMAKZDlNvO4ElHTK4x6vjka42APnwOcEMFHDLXbTZg9CUpd5ALqveowX
123 86 000860z1yhl3i1mKYFMhY4D2kWKA6Bvpfw91VeI7gXyP52PrVbLoP95ykgkz47k3KhCgmgrHq3CBCEdV14aiOa
126 89 00089xfcmZyf8RrftFbxvx9qvJUd8bvG5FKH2Ydz7aN5EsnaBpQkvrTLIsAKNRADeF1M74Ghvk1opzRs28IokPVhS
129 92 00092COlhIGMXrQ4Zl7e6GPlVz43BVWLbnvC3ymtoZ6Itus8KWuM1I31xGPU5Y4vggpcq2g4c6uSvnmUjsAgpYkNoX1u
132 95 00095IrjvnSVC8ECKf2cNUsBkzrSfuTNobIUmAD9BktiMfQSoCBLkwPOa2QmovhnUEpYyAsCKdM2haVqb53PggDviQHseex
135 98 00098DsLvbvWmqgyuWsnQd0DillNmd3LyTSJ98XjKUDhbqBSxhVRoXyv0IkOjWAbZIEb5lmrnISWS28WS4OpisoJYPCIfnB4bw
138 101 00101JNfUNutpjBFhFlhyNhFae2gulYTIfBpfoBbnLl881LPeZNGQkwYF49pbDEvnqYkPSleFUrZ1tEfO4AokI7ka3Gcn8KkTmWWg
141 104 00104lbmN2zeZeUMS6xGQfjtImCkwQwmewbXxsxj0NGETdBGwAfnhBmXOSew8LMdULQYCEA3Nz8ny6OlGfOUP3zjf5lZXlNC8Cn89Il4
144 107 00107UwQCaa4szAYj9if1oIPleauAvyWVkyDzbtZSt0SiKfJgNG7avZLe4TSTWXuEZBOUICfTAjIzVlShwXJ54Oz14rZlBrQL0w05FJsckY
147 110 00110lNZA1HsGmdFZke0Up1PwxPtpt2RFDM9EdOljQ6K3oao44Q6CNsBZHxo56n63Lny5l6k5ny7rhgWtkEGoJS7JbeNBg9ACXApfz4seWiZrX
150 113 00113KJ1sSGNZfZx2xl0MBXY0yf6ybPNjpmYBYiHi0ZsBb9GFuE9hIQgR0TssgbdE9sqq1m90YlS1ZWHSwwElaCkNOT05GbbIt3AfZAzzlpul5jEJ
153 116 001167jYYE6oyKM7qKQdzjpV1xUVUb85hpHpliNZRyiX7r6vJJ4n2FSe9tLUJ4W0ecUEALEemAZ0mUSkSROPl3AdQJ9AFdUAWvT5v4WTbNUZlFk2x0JX
156 119 00119ehpukL2CAOfCDbdtvuEvROVZJUvg044u8YS3d81SQ1FQqZDoVe55F8zCi7ikH1rEk2MWGUQLrmdJkMDKCXrtoeuZBDpo7pJOcmLRYZMLcLiC37iWXx

在 Windows10 上:

101 80 00080Ra86ljAznn9AM17OtGUuFmxdYd7lU1hkInjZoPQJ4C2g3itkqn7wV0thhxPgpxrDimJwUElXzL2
104 83 00083nxTNohavc5sQfvlmnPnGOQNpzn2PKQJTYeDq4I9lMkuMKAxOhdOm1l3KAxmyCNOhlCKla9KMp8XYit
107 86 00086NBNeIqBFwWPbGzvtEihHvFnO3XyfPUEL0izlzF45P0NdfNTCyCDHvO6xa6BX4TyybChCEllhPOFXWpWd4
110 89 00089PmSiJYRGmI2AlXkbFUwcO1Ipr0bFvCmA2Se1A9JGMRTcg7617mXmG7fNCmDZWWFwI5DgTNHtqRDvTzrrmf08
113 92 00092DbsiuxTEZJT8DznuF3mtpdRP4LP4Nboj8tpCbgZkfeeP925U8N7v34qQpT69bw26Lfwp1jJXhkcb1o0wGUsgSIt
116 95 000958GexIZILU3le53WUGzTC6sRLK3vQVCsNI1yOuFt1HdW6QHZm05n5XGGMsluSamrKINAoBPxuQ5yrYSQHE7BlrWI6Jl
119 98 00098suYJVfpHKDkjHmnXwevRUOskhnCfF5Zp2jcN4avlg7ZN9g98G3vFeMpoXrulM7g5VfOQKI7UudzNfqkGDSaNfSuDvfyEE
122 101 00101doDJHZQEJre8aDWDGIPeKzN2aFXKZxYH9w6o9ZxgAXXozc75KMMwQ23YN0N27IMdAY5Oe9WLQSUgIf6AkfSNjWTFOODBvXeg
125 104 00104lhRSLYEXD1waMMkSVKct8jnb8M97rRQl582dlnzRr8hGM00jJLxrhHVvq1Kbu59dtcCSb4vm0KzbXKGiIdarDakNVLuCWYA9Mrh
128 107 00107y11AyDhwM8BZzT73VhkYu9U4ogvbw10ZPmnA824MzAznGbhLbHPDJjnl2NfquwH9XEOTx4vJjz74HC7I8GceZsCTlIQE4tQtWEtmig
131 110 00110GD8f97kpuRShkyrXYI40UvWlWOvskqRrDbUNjR2x6cZcg4NywVe1UAecrehoTJU5WUqZvvxseD16fYFvzaTKv7Jdwn1yQOazXSKheHORZ
134 113 001130coEBOEdkY1raJ65VK77UPU7eRraN2dz9mibcbu4khQwFQWf9WVBPUwTjlddveJKGLKS4gtNLWNeN4U720DW8XmHdpqhkXxqGBouZ2ARYfU6
137 116 001164x8ALzFvQKijeOIcDz6DCBnqzcMPQiR7rLaMBNuNFBYULSJ2xWIcGdyHHZw2lqW817fYo56Yg5hibAO7NzOyehOyxxUA865lQUjiP8LwmffCdnO
140 119 00119Sak3ByDRCFDMYpzpNEIKU5yNEWbWdL0popfhspb8cjE9sEBpMNxyGj5wjofhdois8DYQUTumJ3Xy7nzR04xGCG3mNQkVzKw1d97XP5RwN99Yac6I5F

那么这是什么意思?如果我想生成一个以字节为单位的特定大小的随机字符串,我该怎么办?为什么在两个不同的平台上会有大小差异(我确定是一些 python 内部)?

注意:我的主要目的是生成随机字符串,其大小遵循内存研究问题的特定分布,但这与这里无关。

【问题讨论】:

  • 一个字节=一个字符可能是错误的,关于字符编码。例如,UTF-8 字符可以使用 1 到 4 个字节,从简单字符到更具体的字符。

标签: python string python-2.7 sizeof


【解决方案1】:

Python 字符串对象包含更多信息,而不仅仅是字符。它们包含引用计数、对类型定义的引用、字符串的长度、缓存的散列和实习状态。请参阅PyStringObject struct 以及引用的PyObject_VAR_HEAD struct

因此,空字符串也有内存大小:

>>> import sys
>>> sys.getsizeof('')
37

此大小取决于平台,因为指针和 C 整数在不同平台上具有不同的大小。 37 是 Mac OS X 上 Python 2 str 对象的大小。

对于unicode 对象,图片更加失真; Python 2 可以使用 2 个或 4 个字节每个代码点,这取决于编译时的选择。最新的 Python 3 版本对 Unicode 文本使用可变字节数,每个代码点在 1 到 4 个字节之间,具体取决于文本中的最高代码点要求。

因此,sys.getsizeof() 返回一个不同的更高值是正常sys.getsizeof()不是获取字符串长度的函数。为此使用len()

如果你想知道其他软件为一个字符串使用了多少内存,你肯定不能使用sys.sizeof()的值;其他软件会对如何存储文本做出不同的选择,并且会有不同的开销。 编码 文本的len() 值可能是一个起点,但您必须与其他软件的文档或开发人员联系,看看他们能告诉您多少内存对于给定的一段文本是必需的。

【讨论】:

  • 我对字符串的大小(字节)比长度更感兴趣,所以当我将此字符串存储在memcached 中时,我知道它将占用多少字节。
  • 那仍然是错误的工具。 Memcached 不存储 Python 对象。它存储字节。测量str 的长度,即字节数。
  • 并向 memcached 文档或社区询问每个存储条目的开销是多少。 Python 对 memcached 的作用没有影响。
  • 是的,我同意 memcached 中由于标志和其他原因造成的开销。
  • 字符串实际上并不支持弱引用。大多数 Python 的核心数据类型都没有。
猜你喜欢
  • 1970-01-01
  • 2021-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-04
  • 2021-04-21
相关资源
最近更新 更多