将 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)