거기에 goto
파이썬 또는 이와 동등한 코드의 특정 라인으로 이동 할 수 있도록은?
goto
Fortran 코드를 Python으로 변환 할 때 Python으로 구현 했습니다. 그는 그것을 싫어했다.
거기에 goto
파이썬 또는 이와 동등한 코드의 특정 라인으로 이동 할 수 있도록은?
goto
Fortran 코드를 Python으로 변환 할 때 Python으로 구현 했습니다. 그는 그것을 싫어했다.
답변:
파이썬은 일류 함수를 사용하여 goto로 할 수있는 일을 할 수있는 기능을 제공합니다. 예를 들면 다음과 같습니다.
void somefunc(int a)
{
if (a == 1)
goto label1;
if (a == 2)
goto label2;
label1:
...
label2:
...
}
파이썬에서 다음과 같이 할 수 있습니다 :
def func1():
...
def func2():
...
funcmap = {1 : func1, 2 : func2}
def somefunc(a):
funcmap[a]() #Ugly! But it works.
물론, 그것은 goto를 대체하는 가장 좋은 방법은 아닙니다. 그러나 goto로 무엇을하려고하는지 정확히 알지 못하면 구체적인 조언을하기가 어렵습니다.
@ 아스코 볼 :
최선의 방법은 함수로 묶거나 예외를 사용하는 것입니다. 기능의 경우 :
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
다른 프로그래밍 언어에서 온 경우 예외를 사용하여 이와 같은 작업을 수행하는 것은 약간 어색 할 수 있습니다. 그러나 예외를 사용하는 것을 싫어하면 파이썬이 당신의 언어가 아니라고 주장합니다. :-)
loopfunc
일반적으로 입력과 구현에 더 많은 노력이 필요하지만 대부분의 경우 가장 좋은 방법이라고 생각합니다.
최근 에 파이썬에서 가능하게 하는 함수 데코레이터 를 작성했습니다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
왜 그런 식으로 뭔가를하고 싶은지 잘 모르겠습니다. 즉, 나는 그것에 대해 너무 심각하지 않습니다. 그러나 이런 종류의 메타 프로그래밍은 적어도 CPython과 PyPy에서 파이썬에서 실제로 가능하며 다른 사람이 했던 것처럼 디버거 API를 오용하는 것만이 아니라고 지적하고 싶습니다 . 그래도 바이트 코드를 엉망으로 만들어야합니다.
.begin
및 .end
레이블 만 지원합니까 ?
나는 공식적인 파이썬 디자인 및 역사 FAQ 에서 이것을 발견했다 .
왜 고토가 없습니까?
예외를 사용하여 함수 호출에서도 작동하는 "구조화 된 이동"을 제공 할 수 있습니다. 많은 사람들은 예외가 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
처럼 취급하기 때문에 파이썬을 정말로 좋아 합니다.)
goto
은 확실하게 주요 프로그래밍 문제이지만, 에뮬레이션을위한 IMO 남용 예외 goto
는 약간 더 좋으며 여전히 찌그러져 야합니다. 오히려 파이썬 제작자는 goto
"나쁘고 나쁜 사람"이기 때문에 허용하지 않는 것보다 실제로 유용한 몇 가지 경우에 언어에 포함시킨 다음 동일한 기능 (및 동일한 코드 spaghettification)을 얻기 위해 예외를 남용하는 것이 좋습니다.
의견에서의 제안을 사용하여 @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
루프 파이썬 구문 후에 코드가 모호하게 사용 됩니다. 파이썬이 for 및 while 루프 후에 왜 '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'와 같은 문장을 추가하는 것은 기술적으로 가능합니다. "dis"및 "new"모듈을 사용하여 파이썬 바이트 코드를 스캔하고 수정하는 데 매우 유용합니다.
구현의 주요 아이디어는 먼저 "goto"및 "label"문을 사용하여 코드 블록을 표시하는 것입니다. 특수한 "@goto"데코레이터는 "goto"기능을 표시하기 위해 사용됩니다. 그런 다음이 코드에서 해당 코드를 스캔하고 필요한 수정 사항을 기본 바이트 코드에 적용합니다. 이 모든 것은 소스 코드 컴파일 타임에 발생합니다.
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()
나는 비슷한 것을 찾고 있었다
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)
python goto와 동등한 대신 코드의 빠른 테스트를 위해 다음과 같은 방식으로 break 문을 사용합니다. 이것은 구조화 된 코드베이스를 가지고 있다고 가정합니다. 테스트 변수는 함수가 시작될 때 초기화되며 "if test : break"블록을 중첩 된 if-then 블록 또는 루프의 끝으로 옮기고 테스트하려는 코드의 끝에서 리턴 변수를 수정합니다. 테스트중인 블록 또는 루프 변수를 반영합니다.
def x:
test = True
If y:
# some code
If test:
break
return something
goto/label
파이썬에는 동등한 코드가 없지만 goto/label
루프 사용 과 같은 기능을 여전히 얻을 수 있습니다 .
goto/label
파이썬 이외의 다른 언어로 사용될 수있는 아래에 표시된 코드 샘플을 보자 .
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
와 같이 루프를 사용하여 파이썬에서 위의 코드 샘플과 동일한 기능을 수행 할 수 있습니다 .
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()