Seorang teman saya diimplementasikan gotodalam Python ketika dia menerjemahkan beberapa kode Fortran ke Python. Dia membenci dirinya sendiri untuk itu.
def func1():...def func2():...
funcmap ={1: func1,2: func2}def somefunc(a):
funcmap[a]()#Ugly! But it works.
Memang, itu bukan cara terbaik untuk menggantikan goto. Tetapi tanpa tahu persis apa yang Anda coba lakukan dengan kebagian, sulit untuk memberikan saran khusus.
Taruhan terbaik Anda adalah dengan melampirkannya dalam suatu fungsi atau menggunakan pengecualian. Untuk fungsi:
def loopfunc():while1:while1:if condition:return
Sebagai pengecualian:
try:while1:while1:raiseBreakoutException#Not a real exception, invent your ownexceptBreakoutException:pass
Menggunakan pengecualian untuk melakukan hal-hal seperti ini mungkin terasa sedikit canggung jika Anda berasal dari bahasa pemrograman lain. Tapi saya berpendapat bahwa jika Anda tidak suka menggunakan pengecualian, Python bukan bahasa untuk Anda. :-)
Gunakan dengan bijaksana. Pengecualian dalam Python lebih cepat dari kebanyakan bahasa lain. Tapi mereka masih lambat jika Anda gila dengan mereka.
Jason Baker
Hanya pemberitahuan: loopfuncumumnya akan membutuhkan input dan beberapa upaya lagi untuk diterapkan, tetapi itu adalah cara terbaik dalam banyak kasus saya pikir.
from goto import with_goto
@with_gotodef range(start, stop):
i = start
result =[]
label .begin
if i == stop:
goto .end
result.append(i)
i +=1
goto .begin
label .end
return result
Saya tidak yakin mengapa seseorang ingin melakukan sesuatu seperti itu. Yang mengatakan, saya tidak terlalu serius tentang itu. Tapi saya ingin menunjukkan bahwa pemrograman meta semacam ini sebenarnya mungkin dalam Python, setidaknya dalam CPython dan PyPy, dan tidak hanya dengan menyalahgunakan API debugger seperti yang dilakukan orang lain . Anda harus mengacaukan bytecode.
Anda dapat menggunakan pengecualian untuk memberikan "goto terstruktur" yang bahkan berfungsi lintas panggilan fungsi. Banyak yang merasa bahwa pengecualian dapat dengan mudah meniru semua penggunaan yang masuk akal dari konstruksi “go” atau “goto” dari bahasa C, Fortran, dan lainnya. Sebagai contoh:
class label(Exception):pass# declare a labeltry:...if condition:raise label()# goto label...except label:# where to gotopass...
Ini tidak memungkinkan Anda untuk melompat ke tengah lingkaran, tetapi itu biasanya dianggap sebagai penyalahgunaan goto. Gunakan hemat.
Sangat menyenangkan bahwa ini bahkan disebutkan dalam FAQ resmi, dan bahwa sampel solusi yang bagus disediakan. Saya sangat suka python karena komunitasnya memperlakukan bahkan gotoseperti ini;)
Menyalahgunakan gotoadalah pemrograman utama yang pasti, tetapi pengecualian menyalahgunakan IMO untuk ditiru gotohanya sedikit lebih baik dan masih harus sangat disukai. Saya lebih suka pencipta Python memasukkan gotodalam bahasa untuk beberapa kesempatan di mana itu sebenarnya berguna daripada melarangnya karena "itu buruk, teman-teman" dan kemudian merekomendasikan pengecualian yang menyalahgunakan untuk mendapatkan fungsi yang sama (dan spagettifikasi kode yang sama).
Abion47
15
Untuk menjawab @ascobolpertanyaan menggunakan @bobincesaran dari komentar:
for i in range(5000):for j in range(3000):if should_terminate_the_loop:breakelse:continue# no break encounteredbreak
Saya memperbaiki indentasi blok Anda yang lain, yang mengarah pada penemuan yang menarik :
Braden Best
3
@ B1KMusic: indentasi sudah benar apa adanya. Ini adalah sintaks Python khusus. elsedieksekusi setelah loop jika breakbelum ditemukan. Efeknya adalah bahwa should_terminate_the_loopberakhir baik loop dalam dan luar.
jfs
1
Saya seharusnya menentukan bahwa saya hanya membuat penemuan itu setelah saya mengedit. Sebelum itu, saya pikir saya telah menemukan bug pada penerjemah, jadi saya membuat banyak kasus uji dan melakukan riset untuk memahami apa yang sedang terjadi. Maaf soal itu.
Braden Best
1
Sekarang saya mengerti apa yang sedang terjadi, saya setuju, itu adalah beberapa kode esoterik yang akan dilakukan lebih mudah dengan metode yang lebih tradisional
Braden Best
1
@ B1KMusic: Tidak. Kode duplikat untuk mengatasi ketidaktahuan Anda bukanlah solusi yang baik. Iya. returndisarankan oleh @Jason Baker adalah alternatif yang baik untuk keluar dari loop yang sangat bersarang.
Catatan: Itu ditawarkan sebagai lelucon April Mop. (meskipun bekerja)
# 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"
Tak perlu dikatakan. Ya itu lucu, tapi JANGAN menggunakannya.
terlihat lebih baik bagi saya daripada menggunakan 3 istirahat ... tentu saja ada cara lain untuk menulisnya juga.
Nick
1
@Nick Penggunaan fungsi dengan pengembalian terlihat jauh lebih baik.
Erik Šťastný
7
Label untuk breakdan continuediusulkan dalam PEP 3136 pada tahun 2007, tetapi ditolak. Bagian Motivasi proposal menggambarkan beberapa metode yang umum (jika tidak berlaku) untuk meniru berlabel breakPython.
Secara teknis layak untuk menambahkan pernyataan seperti 'goto' ke python dengan beberapa pekerjaan. Kami akan menggunakan modul "dis" dan "baru", keduanya sangat berguna untuk memindai dan memodifikasi kode byte python.
Gagasan utama di balik implementasi ini adalah untuk pertama menandai blok kode sebagai menggunakan pernyataan "goto" dan "label". Dekorator "@ goto" khusus akan digunakan untuk tujuan menandai fungsi "goto". Setelah itu kami memindai kode itu untuk kedua pernyataan ini dan menerapkan modifikasi yang diperlukan untuk kode byte yang mendasarinya. Ini semua terjadi pada waktu kompilasi kode sumber.
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 gotoswhile 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 +=2continueif 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 jumpsfor label,index in gotos.items():if label notin labels:raiseException("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__':@gotodef test1():print'Hello'
goto .the_end
print'world'
label .the_end
print'the end'
test1()
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 stuffif(condition(e)):
goto B_LOOP;
Jadi pendekatan saya adalah menggunakan boolean untuk membantu keluar dari sarang untuk loop:
for a in xrange(1,10):
get_out =Falsefor b in xrange(1,5):if(get_out):breakfor c in xrange(1,5):if(get_out):breakfor d in xrange(1,5):# do some stuffif(condition(e)):
get_out =Truebreak
Saya menginginkan jawaban yang sama dan saya tidak ingin menggunakannya goto. Jadi saya menggunakan contoh berikut (dari 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)
Sebagai pengganti python goto equivalent saya menggunakan pernyataan break dengan cara berikut untuk tes cepat kode saya. Ini mengasumsikan Anda memiliki basis kode terstruktur. Variabel tes diinisialisasi pada awal fungsi Anda dan saya hanya memindahkan blok "If test: break" ke akhir blok if-then bersarang atau loop yang ingin saya uji, memodifikasi variabel kembali di akhir kode untuk mencerminkan variabel blok atau loop yang saya uji.
def x:
test =TrueIf y:# some codeIf test:breakreturn something
Meskipun tidak ada kode yang setara dengan goto/labelPython, Anda masih bisa mendapatkan fungsionalitas goto/labelmenggunakan loop.
Mari kita ambil contoh kode yang ditunjukkan di bawah ini di mana goto/labeldapat digunakan dalam bahasa arbitrer selain 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...')
Sekarang fungsi yang sama dari contoh kode di atas dapat dicapai dengan python dengan menggunakan whileloop seperti yang ditunjukkan di bawah ini.
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...')
tidak ada cara alternatif untuk mengimplementasikan pernyataan goto
class id:def data1(self):
name=[]
age=[]
n=1while 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])breakexcept:print("list is empty")print("do want to continue y or n")
ch1=input()if ch1=="y":
n=n+1else:print("name \t age")for i in range(n):print(name[i]," \t ",age[i])
n=-1
p1=id()
p1.data1()
goto
dalam Python ketika dia menerjemahkan beberapa kode Fortran ke Python. Dia membenci dirinya sendiri untuk itu.Jawaban:
Tidak, Python tidak mendukung label dan goto, jika itu yang Anda cari. Ini adalah bahasa pemrograman (sangat) terstruktur.
sumber
Python menawarkan Anda kemampuan untuk melakukan beberapa hal yang bisa Anda lakukan dengan goto menggunakan fungsi kelas satu. Sebagai contoh:
Bisa dilakukan dengan python seperti ini:
Memang, itu bukan cara terbaik untuk menggantikan goto. Tetapi tanpa tahu persis apa yang Anda coba lakukan dengan kebagian, sulit untuk memberikan saran khusus.
@ ascobol :
Taruhan terbaik Anda adalah dengan melampirkannya dalam suatu fungsi atau menggunakan pengecualian. Untuk fungsi:
Sebagai pengecualian:
Menggunakan pengecualian untuk melakukan hal-hal seperti ini mungkin terasa sedikit canggung jika Anda berasal dari bahasa pemrograman lain. Tapi saya berpendapat bahwa jika Anda tidak suka menggunakan pengecualian, Python bukan bahasa untuk Anda. :-)
sumber
loopfunc
umumnya akan membutuhkan input dan beberapa upaya lagi untuk diterapkan, tetapi itu adalah cara terbaik dalam banyak kasus saya pikir.Baru-baru ini saya menulis dekorator fungsi yang memungkinkan
goto
dengan Python, seperti itu:Saya tidak yakin mengapa seseorang ingin melakukan sesuatu seperti itu. Yang mengatakan, saya tidak terlalu serius tentang itu. Tapi saya ingin menunjukkan bahwa pemrograman meta semacam ini sebenarnya mungkin dalam Python, setidaknya dalam CPython dan PyPy, dan tidak hanya dengan menyalahgunakan API debugger seperti yang dilakukan orang lain . Anda harus mengacaukan bytecode.
sumber
.begin
dan.end
memberi label?Saya menemukan ini di FAQ Desain dan Sejarah python resmi .
Sangat menyenangkan bahwa ini bahkan disebutkan dalam FAQ resmi, dan bahwa sampel solusi yang bagus disediakan. Saya sangat suka python karena komunitasnya memperlakukan bahkan
goto
seperti ini;)sumber
goto
adalah pemrograman utama yang pasti, tetapi pengecualian menyalahgunakan IMO untuk ditirugoto
hanya sedikit lebih baik dan masih harus sangat disukai. Saya lebih suka pencipta Python memasukkangoto
dalam bahasa untuk beberapa kesempatan di mana itu sebenarnya berguna daripada melarangnya karena "itu buruk, teman-teman" dan kemudian merekomendasikan pengecualian yang menyalahgunakan untuk mendapatkan fungsi yang sama (dan spagettifikasi kode yang sama).Untuk menjawab
@ascobol
pertanyaan menggunakan@bobince
saran dari komentar:Indentasi untuk
else
blok sudah benar. Kode menggunakan tidak jelaselse
setelah sintaks Python loop. Lihat Mengapa python menggunakan 'else' setelah untuk dan sementara loop?sumber
else
dieksekusi setelah loop jikabreak
belum ditemukan. Efeknya adalah bahwashould_terminate_the_loop
berakhir baik loop dalam dan luar.return
disarankan oleh @Jason Baker adalah alternatif yang baik untuk keluar dari loop yang sangat bersarang.Versi yang berfungsi telah dibuat: http://entrian.com/goto/ .
Catatan: Itu ditawarkan sebagai lelucon April Mop. (meskipun bekerja)
Tak perlu dikatakan. Ya itu lucu, tapi JANGAN menggunakannya.
sumber
Label untuk
break
dancontinue
diusulkan dalam PEP 3136 pada tahun 2007, tetapi ditolak. Bagian Motivasi proposal menggambarkan beberapa metode yang umum (jika tidak berlaku) untuk meniru berlabelbreak
Python.sumber
Secara teknis layak untuk menambahkan pernyataan seperti 'goto' ke python dengan beberapa pekerjaan. Kami akan menggunakan modul "dis" dan "baru", keduanya sangat berguna untuk memindai dan memodifikasi kode byte python.
Gagasan utama di balik implementasi ini adalah untuk pertama menandai blok kode sebagai menggunakan pernyataan "goto" dan "label". Dekorator "@ goto" khusus akan digunakan untuk tujuan menandai fungsi "goto". Setelah itu kami memindai kode itu untuk kedua pernyataan ini dan menerapkan modifikasi yang diperlukan untuk kode byte yang mendasarinya. Ini semua terjadi pada waktu kompilasi kode sumber.
Semoga ini menjawab pertanyaan.
sumber
Anda dapat menggunakan Pengecualian Buatan Pengguna Buatan untuk meniru
goto
contoh:
sumber
Python 2 & 3
Tautan: pernyataan-goto
foo.py
sumber
Saya mencari sesuatu yang mirip
Jadi pendekatan saya adalah menggunakan boolean untuk membantu keluar dari sarang untuk loop:
sumber
Ada sekarang. pergi ke
Saya pikir ini mungkin berguna untuk apa yang Anda cari.
sumber
Saya menginginkan jawaban yang sama dan saya tidak ingin menggunakannya
goto
. Jadi saya menggunakan contoh berikut (dari learnpythonthehardway)sumber
Saya punya cara sendiri dalam melakukan goto. Saya menggunakan skrip python terpisah.
Jika saya ingin mengulang:
file1.py
file2.py
file3.py
( CATATAN: Teknik ini hanya berfungsi pada versi Python 2.x)
sumber
Untuk maju Goto, Anda bisa menambahkan:
Ini hanya membantu untuk skenario sederhana (yaitu bersarang ini akan membuat Anda berantakan)
sumber
Sebagai pengganti python goto equivalent saya menggunakan pernyataan break dengan cara berikut untuk tes cepat kode saya. Ini mengasumsikan Anda memiliki basis kode terstruktur. Variabel tes diinisialisasi pada awal fungsi Anda dan saya hanya memindahkan blok "If test: break" ke akhir blok if-then bersarang atau loop yang ingin saya uji, memodifikasi variabel kembali di akhir kode untuk mencerminkan variabel blok atau loop yang saya uji.
sumber
Meskipun tidak ada kode yang setara dengan
goto/label
Python, Anda masih bisa mendapatkan fungsionalitasgoto/label
menggunakan loop.Mari kita ambil contoh kode yang ditunjukkan di bawah ini di mana
goto/label
dapat digunakan dalam bahasa arbitrer selain python.Sekarang fungsi yang sama dari contoh kode di atas dapat dicapai dengan python dengan menggunakan
while
loop seperti yang ditunjukkan di bawah ini.sumber
tidak ada cara alternatif untuk mengimplementasikan pernyataan goto
sumber