そこにあるgoto
Pythonでまたは任意の同等のコードの特定の行にジャンプすることができるようにするには?
goto
いくつかのFortranコードをPythonに変換するときにPythonで実装しました。彼はそれを嫌っていた。
そこにあるgoto
Pythonでまたは任意の同等のコードの特定の行にジャンプすることができるようにするには?
goto
いくつかのFortranコードをPythonに変換するときにPythonで実装しました。彼はそれを嫌っていた。
回答:
Pythonでは、ファーストクラスの関数を使用して、gotoで実行できることのいくつかを実行できます。例えば:
void somefunc(int a)
{
if (a == 1)
goto label1;
if (a == 2)
goto label2;
label1:
...
label2:
...
}
次のようにPythonで行うことができます:
def func1():
...
def func2():
...
funcmap = {1 : func1, 2 : func2}
def somefunc(a):
funcmap[a]() #Ugly! But it works.
確かに、それはgotoの代わりに使用する最良の方法ではありません。しかし、gotoで何をしようとしているのかを正確に知らなければ、具体的なアドバイスをするのは困難です。
@ ascobol:
あなたの最善の策は、それを関数で囲むか、例外を使用することです。関数について:
def loopfunc():
while 1:
while 1:
if condition:
return
例外について:
try:
while 1:
while 1:
raise BreakoutException #Not a real exception, invent your own
except BreakoutException:
pass
例外を使用してこのようなことを行うと、別のプログラミング言語を使用している場合、少し不便に感じるかもしれません。しかし、例外の使用を嫌うなら、Pythonはあなたのための言語ではないと私は主張します。:-)
loopfunc
通常、入力と実装するためのいくつかの努力が必要になりますが、ほとんどの場合、これが最善の方法だと思います。
最近、Pythonで有効にする関数デコレーターを作成goto
しました。
from goto import with_goto
@with_goto
def range(start, stop):
i = start
result = []
label .begin
if i == stop:
goto .end
result.append(i)
i += 1
goto .begin
label .end
return result
なぜそんなことをしたいのかよくわかりません。そうは言っても、私はそれについてあまり真剣ではありません。しかし、この種のメタプログラミングは、Python、少なくともCPythonとPyPyで実際に可能であり、他の人が行ったようにデバッガーAPIを誤用するだけではないことを指摘しておきます。ただし、バイトコードをいじる必要があります。
.begin
と.end
ラベルのみをサポートしていますか?
私はこれを公式のpythonデザインと履歴FAQで見つけました。
なぜ後藤がないの?
例外を使用して、関数呼び出し全体で機能する「構造化されたgoto」を提供できます。多くの人は、例外がC、Fortran、およびその他の言語の「go」または「goto」構成要素のすべての合理的な使用を便利にエミュレートできると感じています。例えば:
class label(Exception): pass # declare a label
try:
...
if condition: raise label() # goto label
...
except label: # where to goto
pass
...
これはループの途中にジャンプすることを許可しませんが、とにかく通常gotoの乱用と見なされます。控えめに使用してください。
これが公式FAQに記載されていることと、素晴らしいソリューションサンプルが提供されていることは非常に素晴らしいことです。コミュニティがgoto
このように扱っているので、私は本当にpythonが好きです;)
goto
確認するために、主要なプログラミングfoux PASのですが、IMOエミュレートするための例外を乱用することはgoto
わずかに優れていると、まだ重くひんしゅくを買うべきです。私はむしろ、Pythonの作成者がgoto
「それは悪いことだ」という理由でそれを許可せずに同じ機能を(そして同じコードのスパゲティフィケーションを取得するため)例外を悪用することを推奨するよりも、実際に役立ついくつかの機会に言語に含めたいと思います。
コメントからのの提案を使用して@ascobol
の質問に回答するには@bobince
:
for i in range(5000):
for j in range(3000):
if should_terminate_the_loop:
break
else:
continue # no break encountered
break
else
ブロックのインデントは正しいです。このコードではelse
、ループ後のPython構文を曖昧にしています。forループとwhileループの後でPythonが 'else'を使用する理由を参照してください。
else
が検出されていない場合は、ループの後に実行されますbreak
。その結果、内部ループと外部ループの両方がshould_terminate_the_loop
終了します。
return
@Jason Bakerによって提案されたのは、深くネストされたループから抜け出すための良い代替手段です。
作業バージョンが作成されました:http : //entrian.com/goto/。
注:エイプリルフールのジョークとして提供されました。(働いています)
# 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"
言うまでもなく。はい、面白いですが、使用しないでください。
「goto」のようなステートメントをpythonに追加していくことは技術的に実現可能です。「dis」モジュールと「new」モジュールを使用します。どちらも、Pythonバイトコードのスキャンと変更に非常に役立ちます。
実装の背後にある主なアイデアは、最初にコードのブロックを「goto」および「label」ステートメントを使用するものとしてマークすることです。特別な「@goto」デコレータは、「goto」関数をマークする目的で使用されます。その後、この2つのステートメントのコードをスキャンし、必要な変更を基になるバイトコードに適用します。これはすべてソースコードのコンパイル時に行われます。
import dis, new
def goto(fn):
"""
A function decorator to add the goto command for a function.
Specify labels like so:
label .foo
Goto labels like so:
goto .foo
Note: you can write a goto statement before the correspnding label statement
"""
labels = {}
gotos = {}
globalName = None
index = 0
end = len(fn.func_code.co_code)
i = 0
# scan through the byte codes to find the labels and gotos
while i < end:
op = ord(fn.func_code.co_code[i])
i += 1
name = dis.opname[op]
if op > dis.HAVE_ARGUMENT:
b1 = ord(fn.func_code.co_code[i])
b2 = ord(fn.func_code.co_code[i+1])
num = b2 * 256 + b1
if name == 'LOAD_GLOBAL':
globalName = fn.func_code.co_names[num]
index = i - 1
i += 2
continue
if name == 'LOAD_ATTR':
if globalName == 'label':
labels[fn.func_code.co_names[num]] = index
elif globalName == 'goto':
gotos[fn.func_code.co_names[num]] = index
name = None
i += 2
# no-op the labels
ilist = list(fn.func_code.co_code)
for label,index in labels.items():
ilist[index:index+7] = [chr(dis.opmap['NOP'])]*7
# change gotos to jumps
for label,index in gotos.items():
if label not in labels:
raise Exception("Missing label: %s"%label)
target = labels[label] + 7 # skip NOPs
ilist[index] = chr(dis.opmap['JUMP_ABSOLUTE'])
ilist[index + 1] = chr(target & 255)
ilist[index + 2] = chr(target >> 8)
# create new function from existing function
c = fn.func_code
newcode = new.code(c.co_argcount,
c.co_nlocals,
c.co_stacksize,
c.co_flags,
''.join(ilist),
c.co_consts,
c.co_names,
c.co_varnames,
c.co_filename,
c.co_name,
c.co_firstlineno,
c.co_lnotab)
newfn = new.function(newcode,fn.func_globals)
return newfn
if __name__ == '__main__':
@goto
def test1():
print 'Hello'
goto .the_end
print 'world'
label .the_end
print 'the end'
test1()
これが質問に答えることを願っています。
ユーザー定義の例外を使用してエミュレートできますgoto
例:
class goto1(Exception):
pass
class goto2(Exception):
pass
class goto3(Exception):
pass
def loop():
print 'start'
num = input()
try:
if num<=0:
raise goto1
elif num<=2:
raise goto2
elif num<=4:
raise goto3
elif num<=6:
raise goto1
else:
print 'end'
return 0
except goto1 as e:
print 'goto1'
loop()
except goto2 as e:
print 'goto2'
loop()
except goto3 as e:
print 'goto3'
loop()
pip3 install goto-statement
Python 2.6から3.6およびPyPyでテストされています。
リンク:goto-statement
foo.py
from goto import with_goto
@with_goto
def bar():
label .bar_begin
...
goto .bar_begin
私はに似たものを探していました
for a in xrange(1,10):
A_LOOP
for b in xrange(1,5):
for c in xrange(1,5):
for d in xrange(1,5):
# do some stuff
if(condition(e)):
goto B_LOOP;
したがって、私のアプローチは、ブール値を使用して、ネストされたforループから抜け出すのを助けることでした:
for a in xrange(1,10):
get_out = False
for b in xrange(1,5):
if(get_out): break
for c in xrange(1,5):
if(get_out): break
for d in xrange(1,5):
# do some stuff
if(condition(e)):
get_out = True
break
同じ答えが欲しくて使用したくありませんgoto
でした。だから私は次の例を使用しました(learnpythonthehardwayから)
def sample():
print "This room is full of gold how much do you want?"
choice = raw_input("> ")
how_much = int(choice)
if "0" in choice or "1" in choice:
check(how_much)
else:
print "Enter a number with 0 or 1"
sample()
def check(n):
if n < 150:
print "You are not greedy, you win"
exit(0)
else:
print "You are nuts!"
exit(0)
goto/label
Pythonに相当するコードはありませんが、次のような機能を取得できます。goto/label
ループ使用する使用できます。
goto/label
Python以外の任意の言語で使用できる以下のコードサンプルを見てみましょう。
String str1 = 'BACK'
label1:
print('Hello, this program contains goto code\n')
print('Now type BACK if you want the program to go back to the above line of code. Or press the ENTER key if you want the program to continue with further lines of code')
str1 = input()
if str1 == 'BACK'
{
GoTo label1
}
print('Program will continue\nBla bla bla...\nBla bla bla...\nBla bla bla...')
これで、上記のコードサンプルと同じ機能を、while
以下に示すようにループを使用してPythonで実現できます。
str1 = 'BACK'
while str1 == 'BACK':
print('Hello, this is a python program containing python equivalent code for goto code\n')
print('Now type BACK if you want the program to go back to the above line of code. Or press the ENTER key if you want the program to continue with further lines of code')
str1 = input()
print('Program will continue\nBla bla bla...\nBla bla bla...\nBla bla bla...')
gotoステートメントを実装する代替方法はありません
class id:
def data1(self):
name=[]
age=[]
n=1
while n>0:
print("1. for enter data")
print("2. update list")
print("3. show data")
print("choose what you want to do ?")
ch=int(input("enter your choice"))
if ch==1:
n=int(input("how many elemet you want to enter="))
for i in range(n):
name.append(input("NAME "))
age.append(int(input("age ")))
elif ch==2:
name.append(input("NAME "))
age.append(int(input("age ")))
elif ch==3:
try:
if name==None:
print("empty list")
else:
print("name \t age")
for i in range(n):
print(name[i]," \t ",age[i])
break
except:
print("list is empty")
print("do want to continue y or n")
ch1=input()
if ch1=="y":
n=n+1
else:
print("name \t age")
for i in range(n):
print(name[i]," \t ",age[i])
n=-1
p1=id()
p1.data1()