将apply()从Python2移植到Python3



我正在将一些遗留的python2代码迁移到python3,并且遇到了这个函数:

FRAMESTART_A = 231
FRAMETYPE_VIDEO = 6
def prepMessage(self, x):
self.nextMessage = []
bytes = []
bytes.append(FRAMESTART_A)  # frame start
bytes.append(FRAMETYPE_VIDEO)  # addresss
for n in range(self.width):
# set values from [0, width]
value = 65535 * 
(1.0 - (math.pow(0.5 * (math.sin(x / 2000 + time.time()) + 1), 4)))
bytes.append(value)
for n in range(50 - self.width):
# set bytes from [width, :] to zero
bytes.append(0)
message = apply(struct.pack,["BB"+"H"*(len(bytes)-2)]+bytes)
self.nextMessage.append(message)

从概念上讲,我得到这是创建一个总是50字节长的项的字节数组,最后一个字节填充为零。在Python3中,apply()不再存在,所以问题在于:

message = apply(struct.pack,["BB"+"H"*(len(bytes)-2)]+bytes)

阅读文档,看起来我可以使用*操作符将函数应用于参数列表,如下所示:

message = struct.pack(*(["BB" + "H" * (len(bytes) - 2)] + bytes))

但是这会产生一个运行时错误:

message = struct.pack(*(["BB" + "H" * (len(bytes) - 2)] + bytes))
struct.error: required argument is not an integer

查看python3struct.pack文档,看起来我应该输入一个格式字符串,看起来像"BBHHHHHHH…"然后给它一个字节数组。但是,原始代码可以工作!所以我不确定message = apply(struct.pack,["BB"+"H"*(len(bytes)-2)]+bytes)是如何工作的,除非struct.pack在python2中工作有很大不同。

如何将其移植到工作代码中?

如果你想在Python 3中重新创建apply,这很容易:

def apply(func, args, kwargs=None):
return func(*args) if kwargs is None else func(*args, **kwargs)

如果你想让代码在Py2或Py3上工作,只要把这个放在你的文件的顶部,当它没有提供时,做一个后备apply:

try:
apply
except NameError:
def apply(func, args, kwargs=None):
return func(*args) if kwargs is None else func(*args, **kwargs)

也就是说,在Py2或Py3上都不需要apply;每当你看到:

apply(somefunc, someargs)

像这样,你可以把它改成:

somefunc(*someargs)

所以在这个例子中,它应该是:

message = struct.pack(*["BB"+"H"*(len(bytes)-2)]+bytes)

或者更简单(因为当你只传递一个内容并解包其余内容而不需要额外的临时内容时,将一个内容连接到前面只是为了立即解包是不必要的):

message = struct.pack("BB"+"H"*(len(bytes)-2), *bytes)

最新更新