男孩我不理解python pass-by-reference问题...我创建了非常有用的“unpacker”类,我将它传递给需要从中解压缩的各种对象,但是它的速度非常慢。 ,我可以告诉它每次传递BU对象时都会制作binaryStr的副本。我知道这一点,因为如果我将BU分成更小的块,它运行速度快100倍(我最初使用它来保存16MB文件I / O缓冲区)
所以我的问题是,为什么该成员没有通过引用传递,有没有办法强迫它?我很确定BU对象本身是通过引用传递的(因为我的代码工作),但速度表明复制了.binaryStr对象。是否有一些我想念的更微妙的东西?
class BinaryUnpacker(object):
def __init__(self, binaryStr):
self.binaryStr = binaryStr
self.pos = 0
def get(self, varType, sz=0):
pos = self.pos
if varType == UINT32:
value = unpack('<I', self.binaryStr[pos:pos+4])[0]
self.pos += 4
return value
elif varType == UINT64:
value = unpack('<Q', self.binaryStr[pos:pos+8])[0]
self.pos += 8
return value
elif varType == VAR_INT:
[value, nBytes] = unpackVarInt(self.binaryStr[pos:])
self.pos += nBytes
....
对此的用例类似于:
def unserialize(self, toUnpack):
if isinstance(toUnpack, BinaryUnpacker):
buData = toUnpack
else: # assume string
buData = BinaryUnpacker(toUnpack)
self.var1 = buData.get(VAR_INT)
self.var2 = buData.get(BINARY_CHUNK, 64)
self.var3 = buData.get(UINT64)
self.var4obj = AnotherClass().unserialize(buData)
非常感谢你的帮助。
答案 0 :(得分:4)
在对字符串进行切片以获取子字符串时会生成副本。例如:
[value, nBytes] = unpackVarInt(self.binaryStr[pos:])
这将创建从索引pos
到结尾的字符串副本,这可能需要一段时间才能生成长字符串。如果你可以在获取子字符串之前确定实际需要的字节数,然后使用self.binaryStr[pos:pos+nBytes]
,因为获取一个小的子字符串相对较快。
请注意,时间仅取决于子字符串的长度,因此无论self.binaryStr[pos:pos+4]
的长度如何,self.binaryStr
都应占用大致相同的时间。
答案 1 :(得分:3)
我没有深入查看您的代码,但是可以使用buffer()
访问公开memoryview objects
方法(例如字符串)的类型,而无需复制数据。 Here's the relevant documentation为此。
您可以使用memoryview
对象而不是切割字符串:这样您就可以绕过当前代码的耗时过程。
前几天我问a question这个可能对你有用的事情。
答案 2 :(得分:0)
我认为仅靠速度判断是不合适的。你说你可以告诉你正在复制字符串,因为如果你将它分成更小的块,它运行得更快。但是你没有详细介绍的unpack()函数的运行时间也可能取决于数据大小。
此外,切片
等字符串unpack('<I', self.binaryStr[pos:pos+4])[0]
将创建新的字符串对象,因为字符串是不可变对象。