Goto для Python
Оригинальная статья: goto for Python
Автор статьи: Ричи Хиндл (Richie Hindle)
Источник: http://entrian.com/goto/
Модуль «Гото» была первоапрельская шутка, опубликованный 1 апреля 2004 г. Да, это работает, но это шутка, тем не менее. Пожалуйста, не используйте его в реальном коде!
Добавляет ключевые слова 'goto' и 'comefrom' для Python.
Ключевые слова 'goto' и 'comefrom' добавляют гибкость механизмам управления потоком Python и позволяют программистам Python использовать многие общие идиомы потока управления, которые ранее им отказывали. Ниже приведены некоторые примеры.
Чтобы включить новые ключевые слова, добавьте следующую строку в начало вашего кода:
from goto import goto, comefrom, label
goto
'goto' переводит выполнение программы непосредственно в другую строку кода. Целевая линия должна быть идентифицирована с помощью оператора 'label'. Этикетки определяются с использованием ключевого слова 'label' и имеют имена, которые являются произвольными идентификаторами Python с префиксом одной точки, например:
label .myLabel
Чтобы перейти к метке, используйте ключевое слово 'goto' следующим образом:
goto .myLabel
Вычисленный goto
Вы можете использовать вычисляемый goto, назначив имя метки переменной во время выполнения и ссылаясь на нее, используя следующую звездочку:
x = calculateLabelName()
goto *x
Значение «x» не должно содержать ведущую точку. См. Пример 5 ниже для полного примера.
comefrom
'comefrom' - это противоположность 'goto'. Это позволяет кусочку кода сказать «Когда бы ни была достигнута метка X, перейдите сюда». Например:
# ...code 1...
label .somewhere
# ...code 2...
comefrom .somewhere
Здесь «code 2» не будет выполняться - выполнение перейдет непосредственно из строки «label.somewhere» в строку «comefrom.somewhere». 'comefrom' обычно используется в качестве средства отладки - его использование в производственном коде не рекомендуется, поскольку оно может привести к неожиданному поведению.
Ограничения
Есть некоторые классы goto и comefrom, которые были бы неписаны, и, следовательно, есть некоторые ограничения на то, куда могут идти прыжки:
- Никаких переходов между модулями или функциями
- Никакой прыжок в середину цикла или предложение 'final'
- Нет прыжка на строку 'except' (потому что нет исключения)
Примеры
Вот несколько примеров того, как можно использовать goto и comefrom:
# Example 1: Breaking out from a deeply nested loop:
from goto import goto, label
for i in range(1, 10):
for j in range(1, 20):
for k in range(1, 30):
print i, j, k
if k == 3:
goto .end
label .end
print "Finished\n"
# Example 2: Restarting a loop:
from goto import goto, label
label .start
for i in range(1, 4):
print i
if i == 2:
try:
output = message
except NameError:
print "Oops - forgot to define 'message'! Start again."
message = "Hello world"
goto .start
print output, "\n"
# Example 3: Cleaning up after something fails:
from goto import goto, label
# Imagine that these are real worker functions.
def setUp(): print "setUp"
def doFirstTask(): print 1; return True
def doSecondTask(): print 2; return True
def doThirdTask(): print 3; return False # This one pretends to fail.
def doFourthTask(): print 4; return True
def cleanUp(): print "cleanUp"
# This prints "setUp, 1, 2, 3, cleanUp" - no "4" because doThirdTask fails.
def bigFunction1():
setUp()
if not doFirstTask():
goto .cleanup
if not doSecondTask():
goto .cleanup
if not doThirdTask():
goto .cleanup
if not doFourthTask():
goto .cleanup
label .cleanup
cleanUp()
bigFunction1()
print "bigFunction1 done\n"
# Example 4: Using comefrom to let the cleanup code take control itself.
from goto import comefrom, label
def bigFunction2():
setUp()
if not doFirstTask():
label .failed
if not doSecondTask():
label .failed
if not doThirdTask():
label .failed
if not doFourthTask():
label .failed
comefrom .failed
cleanUp()
bigFunction2()
print "bigFunction2 done\n"
# Example 5: Using a computed goto:
from goto import goto, label
label .getinput
i = raw_input("Enter either 'a', 'b' or 'c', or any other letter to quit: ")
if i in ('a', 'b', 'c'):
goto *i
else:
goto .quit
label .a
print "You typed 'a'"
goto .getinput
label .b
print "You typed 'b'"
goto .getinput
label .c
print "You typed 'c'"
goto .getinput
label .quit
print "Finished\n"
# Example 6: What happens when a label is missing:
from goto import goto, label
label .real
goto .unreal # Raises a MissingLabelError exception.
Этот модуль выпущен под лицензией Python Software Foundation, который можно найти по адресу http://www.python.org/ Для этого требуется Python 2.3 или новее.
Ричи Хиндл, [email protected]
Версия 1.0, выпущенная 1 апреля 2004 года. Скачайте здесь.