3

我试图理解一些 python 2.5 代码,我遇到了这种模式:

def __init__(self, matrix, top_buttons, side_buttons, config_button):
        raise isinstance(matrix, ButtonMatrixElement) or AssertionError
        raise matrix.width() == 8 and matrix.height() == 8 or AssertionError
        raise isinstance(top_buttons, tuple) or AssertionError
        raise len(top_buttons) == 8 or AssertionError
        raise isinstance(side_buttons, tuple) or AssertionError
        raise len(side_buttons) == 8 or AssertionError
        raise isinstance(config_button, ButtonElement) or AssertionError

我尝试在 shell 中使用一些简单的条件语句进行测试,如下所示:

>>> str = 'hello'
>>> raise len(str) == 5 or AssertionError

Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    raise len(str) == 5 or AssertionError
TypeError: exceptions must be classes, instances, or strings (deprecated), not bool

所以从这个测试来看,至少我试过的方式,你不能提出布尔语句。那么引发条件表达式是什么意思,为什么它在函数中__init__起作用但在我的测试代码中不起作用?

4

2 回答 2

8

正如您所发现的,代码是无稽之谈,是对看起来像是失败的assert语句的拙劣尝试。

他们应该写的是:

assert isinstance(matrix, ButtonMatrixElement)

等等。

您似乎找到了反编译的 Ableton Live 脚本,但反编译脚本生成了错误的 Python 代码。an 的字节码assert如下所示(Python 2.5 字节码):

>>> import dis
>>> dis.dis(compile('''assert isinstance(matrix, ButtonMatrixElement)''', '<stdin>', 'exec'))
  1           0 LOAD_NAME                0 (isinstance)
              3 LOAD_NAME                1 (matrix)
              6 LOAD_NAME                2 (ButtonMatrixElement)
              9 CALL_FUNCTION            2
             12 JUMP_IF_TRUE             7 (to 22)
             15 POP_TOP             
             16 LOAD_GLOBAL              3 (AssertionError)
             19 RAISE_VARARGS            1
        >>   22 POP_TOP             
             23 LOAD_CONST               0 (None)
             26 RETURN_VALUE        

看起来好像任何用于反编译字节码的自动化过程都将其转换为您看到的代码,而不是将其识别为assert.

但是请注意,如果isinstance()调用返回True,则跳转指令(索引 12,JUMP_IF_TRUE)会跳过指令RAISE_VARARGS,而重新构造的代码则不会。将此与实际raise ... or ...语句进行比较,您会注意到跳转没有超过raise

>>> dis.dis(compile('raise foo or bar', '<stdin>', 'exec'))
  1           0 LOAD_NAME                0 (foo)
              3 JUMP_IF_TRUE             4 (to 10)
              6 POP_TOP             
              7 LOAD_NAME                1 (bar)
        >>   10 RAISE_VARARGS            1
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE        

据推测,代码生成器并不复杂,无法处理这个问题;如果您假设只or生成JUMP_IF_TRUE并且不正确处理偏移量,您可以看到错误是如何产生的。

于 2014-10-13T09:20:33.593 回答
2

正如之前已经回答的那样,这是反编译器中的一个错误,已在对python字节码进行逆向工程的过程中使用。如果您想自己反编译文件,可以使用以下版本的脚本:

https://github.com/frankebersoll/uncompyle2

上述错误应该在那里修复。当你MainSelectorComponent.pyc用这个版本反编译时,你会得到:

class MainSelectorComponent(ModeSelectorComponent):
    """ Class that reassigns the button on the launchpad to different functions """

    def __init__(self, matrix, top_buttons, side_buttons, config_button):
        assert isinstance(matrix, ButtonMatrixElement)
        assert matrix.width() == 8 and matrix.height() == 8
        assert isinstance(top_buttons, tuple)
        assert len(top_buttons) == 8
        assert isinstance(side_buttons, tuple)
        assert len(side_buttons) == 8
        assert isinstance(config_button, ButtonElement)
于 2014-12-02T21:45:28.900 回答