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

次のような単純な条件ステートメントを使用して、シェルでこれをテストしてみました。

>>> 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 コードを生成していました。のバイトコードは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 に答える