2014-10-13 3 views
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__, но не в моем тестовом коде?

+3

Этот шаблон делает ** нет смысла ** вообще. –

+0

Единственный способ использовать условное выражение, когда 'raise'-ing будет, например. 'raise SomeError, если условие else AnotherError', но это кажется бесполезным сбивающим с толку. – jonrsharpe

ответ

8

Код - это вздор, неудачная попытка сделать что-то похожее на assert statement, что не удается, как вы обнаружили.

То, что они должны написали это:

assert isinstance(matrix, ButtonMatrixElement) 

и так далее.

Похоже, вы нашли decompiled Ableton Live scripts, но сценарий декомпилирования произвел неправильный код 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 и не обрабатывает смещения должным образом, вы можете увидеть, как была сделана ошибка.

+1

Возможно ли, что автор этого кода мог переопределить, как работает ключевое слово 'raise'? Единственная причина, по которой я сомневаюсь, заключается в том, что эта программа действительно работает.Если это ошибка, и нет никаких шансов, есть какой-то странный, запутанный стиль кода, возможно ли, что эта программа все равно будет выполняться и что это ошибка, которая не остановит выполнение? –

+0

Насколько вы уверены, что этот код действительно выполняется? Потому что вы не можете переопределить 'raise' без исправления кода интерпретатора C и перекомпиляции. –

+0

Если бы этот код действительно выполнялся, и * ничего не было исключением *, программа действительно остановилась бы, да. –

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) 
+0

Спасибо! Просто использовал это с помощью сценариев управления Push. – cce