Có một goto
hoặc bất kỳ tương đương trong Python để có thể nhảy đến một dòng mã cụ thể không?
goto
bằng Python khi anh ta đang dịch một số mã Fortran sang Python. Anh ghét bản thân mình vì điều đó.
Có một goto
hoặc bất kỳ tương đương trong Python để có thể nhảy đến một dòng mã cụ thể không?
goto
bằng Python khi anh ta đang dịch một số mã Fortran sang Python. Anh ghét bản thân mình vì điều đó.
Câu trả lời:
Python cung cấp cho bạn khả năng thực hiện một số điều bạn có thể làm với một goto sử dụng các hàm hạng nhất. Ví dụ:
void somefunc(int a)
{
if (a == 1)
goto label1;
if (a == 2)
goto label2;
label1:
...
label2:
...
}
Có thể được thực hiện trong python như thế này:
def func1():
...
def func2():
...
funcmap = {1 : func1, 2 : func2}
def somefunc(a):
funcmap[a]() #Ugly! But it works.
Cấp, đó không phải là cách tốt nhất để thay thế cho goto. Nhưng không biết chính xác những gì bạn đang cố gắng làm với goto, thật khó để đưa ra lời khuyên cụ thể.
@ ascobol :
Đặt cược tốt nhất của bạn là hoặc đặt nó trong một chức năng hoặc sử dụng một ngoại lệ. Đối với chức năng:
def loopfunc():
while 1:
while 1:
if condition:
return
Ngoại lệ:
try:
while 1:
while 1:
raise BreakoutException #Not a real exception, invent your own
except BreakoutException:
pass
Sử dụng ngoại lệ để làm những việc như thế này có thể cảm thấy hơi khó xử nếu bạn đến từ một ngôn ngữ lập trình khác. Nhưng tôi sẽ lập luận rằng nếu bạn không thích sử dụng ngoại lệ, Python không phải là ngôn ngữ dành cho bạn. :-)
loopfunc
thường sẽ yêu cầu đầu vào và một số nỗ lực hơn để thực hiện, nhưng đó là cách tốt nhất trong hầu hết các trường hợp tôi nghĩ.
Gần đây tôi đã viết một trình trang trí chức năng cho phép goto
trong Python, giống như vậy:
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
Tôi không chắc tại sao người ta lại muốn làm một cái gì đó như thế. Điều đó nói rằng, tôi không quá nghiêm trọng về nó. Nhưng tôi muốn chỉ ra rằng loại lập trình meta này thực tế có thể có trong Python, ít nhất là trong CPython và PyPy, và không chỉ bằng cách lạm dụng API trình gỡ lỗi như những người khác đã làm. Bạn phải lộn xộn với mã byte mặc dù.
.begin
và .end
nhãn?
Tôi tìm thấy điều này trong Câu hỏi thường gặp về Thiết kế và Lịch sử của python .
Tại sao không có goto?
Bạn có thể sử dụng các trường hợp ngoại lệ để cung cấp một goto có cấu trúc của Youtube mà thậm chí hoạt động trên các lệnh gọi hàm. Nhiều người cảm thấy rằng các trường hợp ngoại lệ có thể mô phỏng một cách thuận tiện tất cả các cách sử dụng hợp lý của các cấu trúc của trò chơi go go hay hoặc goto của C, Fortran và các ngôn ngữ khác. Ví dụ:
class label(Exception): pass # declare a label
try:
...
if condition: raise label() # goto label
...
except label: # where to goto
pass
...
Điều này không cho phép bạn nhảy vào giữa vòng lặp, nhưng dù sao đó thường được coi là lạm dụng goto. Sử dụng một cách tiết kiệm.
Thật tuyệt khi điều này thậm chí còn được đề cập trong Câu hỏi thường gặp chính thức và một mẫu giải pháp tốt được cung cấp. Tôi thực sự thích trăn vì cộng đồng của nó đang đối xử goto
như thế này;)
goto
là một chương trình chính yếu để đảm bảo, nhưng IMO lạm dụng các ngoại lệ để mô phỏng goto
chỉ tốt hơn một chút và vẫn nên được tán thành. Tôi muốn thay vào đó, những người tạo Python bao gồm goto
ngôn ngữ trong một số trường hợp thực sự hữu ích hơn là không cho phép vì "nó xấu, các bạn" và sau đó khuyên bạn nên lạm dụng các ngoại lệ để có cùng chức năng (và cùng một mã spaghettization).
Để trả lời @ascobol
câu hỏi bằng cách sử dụng @bobince
đề xuất từ các nhận xét:
for i in range(5000):
for j in range(3000):
if should_terminate_the_loop:
break
else:
continue # no break encountered
break
Việc thụt lề cho else
khối là chính xác. Mã sử dụng tối nghĩa else
sau một cú pháp Python lặp. Xem tại sao python sử dụng 'other' sau vòng lặp for và while?
else
được thực hiện sau vòng lặp nếu break
không gặp phải. Hiệu quả là should_terminate_the_loop
chấm dứt cả các vòng bên trong và bên ngoài.
return
được đề xuất bởi @Jason Baker là một lựa chọn tốt để thoát ra khỏi các vòng lặp được lồng sâu.
Một phiên bản làm việc đã được thực hiện: http://entrian.com/goto/ .
Lưu ý: Nó được cung cấp như một trò đùa Cá tháng Tư. (mặc dù làm việc)
# 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"
Không cần nói rằng. Có nó buồn cười, nhưng KHÔNG sử dụng nó.
Về mặt kỹ thuật có thể thêm một câu lệnh 'goto' vào python với một số công việc. Chúng tôi sẽ sử dụng các mô-đun "dis" và "new", cả hai đều rất hữu ích để quét và sửa đổi mã byte python.
Ý tưởng chính đằng sau việc triển khai là trước tiên đánh dấu một khối mã là sử dụng các câu lệnh "goto" và "nhãn". Một trình trang trí "@goto" đặc biệt sẽ được sử dụng cho mục đích đánh dấu các chức năng "goto". Sau đó, chúng tôi quét mã đó cho hai câu lệnh này và áp dụng các sửa đổi cần thiết cho mã byte bên dưới. Tất cả điều này xảy ra tại thời gian biên dịch mã nguồn.
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()
Hy vọng điều này trả lời câu hỏi.
bạn có thể sử dụng Ngoại lệ do người dùng xác định để mô phỏnggoto
thí dụ:
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
Đã thử nghiệm trên Python 2.6 đến 3.6 và PyPy.
Liên kết: tuyên bố goto
foo.py
from goto import with_goto
@with_goto
def bar():
label .bar_begin
...
goto .bar_begin
Tôi đang tìm kiếm một số thứ tương tự như
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;
Vì vậy, cách tiếp cận của tôi là sử dụng một boolean để giúp thoát ra khỏi các vòng lặp lồng nhau:
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
Tôi muốn câu trả lời tương tự và tôi không muốn sử dụng goto
. Vì vậy, tôi đã sử dụng ví dụ sau (từ 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)
Tôi có cách làm gotos của riêng tôi. Tôi sử dụng các kịch bản python riêng biệt.
Nếu tôi muốn lặp:
file1.py
print("test test")
execfile("file2.py")
a = a + 1
file2.py
print(a)
if a == 10:
execfile("file3.py")
else:
execfile("file1.py")
file3.py
print(a + " equals 10")
( LƯU Ý: Kỹ thuật này chỉ hoạt động trên các phiên bản Python 2.x)
Thay cho một python goto tương đương, tôi sử dụng câu lệnh break theo kiểu sau để kiểm tra nhanh mã của tôi. Điều này giả định rằng bạn có cơ sở mã cấu trúc. Biến kiểm tra được khởi tạo khi bắt đầu chức năng của bạn và tôi chỉ cần di chuyển khối "If test: break" đến cuối khối if-then lồng nhau hoặc vòng lặp tôi muốn kiểm tra, sửa đổi biến trả về ở cuối mã để phản ánh khối hoặc biến vòng lặp tôi đang thử nghiệm.
def x:
test = True
If y:
# some code
If test:
break
return something
Mặc dù không có bất kỳ mã nào tương đương với goto/label
Python, bạn vẫn có thể có chức năng goto/label
sử dụng các vòng lặp như vậy .
Hãy lấy một mẫu mã được hiển thị bên dưới, nơi goto/label
có thể được sử dụng trong một ngôn ngữ tùy ý khác với 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...')
Bây giờ chức năng tương tự của mẫu mã trên có thể đạt được trong python bằng cách sử dụng một while
vòng lặp như dưới đây.
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...')
không có cách nào khác để thực hiện câu lệnh 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()