【问题标题】:Porting apply() from Python2 to Python3将 apply() 从 Python2 移植到 Python3
【发布时间】:2021-10-30 09:11:08
【问题描述】:

我正在将一些遗留的 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 中的工作方式大不相同。

什么是正确的方式来移植这个以获得工作代码?

【问题讨论】:

  • 您可以将其简化为 struct.pack("BB" + "H" * (len(bytes) - 2), *bytes),尽管我认为这不能解决错误。
  • 另外,我不认为value 被使用了?应该用brightness 替换吗?
  • 你能提供bytes的样本数据吗?
  • 应该是struct.pack("BB" + "H" * (len(bytes) - 2), *bytes),而不是struct.pack(["BB" + "H" * (len(bytes) - 2)], *bytes)。注意没有[ ]
  • 既然你正在重写这个,最好将你的字节列表命名为别的东西,因为bytes 是一个内置的类类型

标签: python-3.x python-2.7 apply porting


【解决方案1】:

如果你想在 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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-11
    • 2018-05-30
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    相关资源
    最近更新 更多