将 apply() 从 Python2 移植到 Python3
Porting apply() from Python2 to 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
查看 python3 struct.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)
我正在将一些遗留 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
查看 python3 struct.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)