циклы — Python как остановить цикл по клику пункта меню?
Одна опечатка и одна принципиальная ошибка.
Опечатка в присваивании:
if work: work==False # должно быть просто =
А ошибка в том, что вы снова вызываете move_clockwise()
в конце функции def move_counterclockwise()
. В результате функции уходят в рекурсию и никогда не возвращаются в цикл проверки условия на останов:
while work: move_clockwise()
Ну и work = True
надо бы добавить в начало def start(event):
. Чтобы можно было снова запустить движение овала.
Ну а вообще, код можно подсократить. И останавливаться мгновенно.
from tkinter import * import random import time #from PIL import ImageTk, Image root = Tk() root.title("Лабораторная работа №4") root.geometry('360x360') width=360 height=360 sleep=0.02 step=15 work=False c = Canvas(root, width=width, height=height, bg="white") c.place(x = 0, y = 0) oval = c. create_oval(0, 0, 30, 30, fill='green') def move(figure): while True: for vertical, increment in ((False, +1), (True , +1), (False, -1), (True , -1), # по часовой (True , +1), (False, +1), (True , -1), (False, -1)): # против часовой for i in range(((height if vertical else width) - 30) // step): if not work: c.coords(figure, 0, 0, 30, 30) return c.move(figure, (0 if vertical else 1) * step * increment, (1 if vertical else 0) * step * increment) root.update() time.sleep(sleep) def start(event): global work if not work: work = True move(oval) def stop(): global work work = False #Заполнение матрицы for x in range(6): for y in range(6): text=c.create_text(30+60*x, 30+60*y, text=str(random.randint(0,99))) c.bind('<Double-Button-1>', start) menu=Menu(root) root.config(menu=menu) menu.add_command(label="Stop", command=stop) root.mainloop()
К тому же задание довольно невнятное. С учётом того, что движение должно происходить с дискретом 0.8 секунды (а это довольно большая пауза), возможно имелось ввиду, что овал должен прыгать по элементам матрицы. И в таком случае time.sleep()
вообще применять нельзя, т.к. он будет фризить интерфейс на это время. Нужно использовать функцию after()
для отложенного запуска следующего перемещения. Например, с использованием генератора, код может выглядеть так:
from tkinter import * import random import time #from PIL import ImageTk, Image root = Tk() root.title("Лабораторная работа №4") sleep = 0.8 step = 60 oval_size = 40 matrix_size = {"W":6, "H":6} # width, height offset = (step - oval_size) // 2 work = False root.geometry(f'{matrix_size["W"] * step}x{matrix_size["H"] * step}') c = Canvas(root, width=matrix_size["W"] * step, height=matrix_size["H"] * step, bg="white") c.place(x = 0, y = 0) oval = c.create_oval(offset, offset, offset + oval_size, offset + oval_size) def move(gen=None): if work: next(gen) root.after(int(sleep*1000), lambda: move(gen)) def move_generator(): while True: for vertical, increment in ((False, +1), (True , +1), (False, -1), (True , -1), # по часовой (True , +1), (False, +1), (True , -1), (False, -1)): # против часовой for i in range(matrix_size["H" if vertical else "W"] - 1): c.move(oval, (0 if vertical else 1) * step * increment, (1 if vertical else 0) * step * increment) yield def start(event): global work if not work: work = True move(move_generator()) def stop(): global work work = False c.coords(oval, offset, offset, offset + oval_size, offset + oval_size) #Заполнение матрицы for x in range(6): for y in range(6): text=c.create_text(30+60*x, 30+60*y, text=str(random.randint(0,99))) c.bind('<Double-Button-1>', start) menu=Menu(root) root. config(menu=menu) menu.add_command(label="Stop", command=stop) root.mainloop()
Оно же без использования генератора.
from tkinter import * import random import time root = Tk() root.title("Лабораторная работа №4") sleep = 0.8 step = 60 oval_size = 40 matrix_size = {"W":6, "H":6} # width, height offset = (step - oval_size) // 2 work = False root.geometry(f'{matrix_size["W"] * step}x{matrix_size["H"] * step}') c = Canvas(root, width=matrix_size["W"] * step, height=matrix_size["H"] * step, bg="white") c.place(x = 0, y = 0) oval = c.create_oval(offset, offset, offset + oval_size, offset + oval_size) movements = [] for vertical, increment in ((False, +1), (True , +1), (False, -1), (True , -1), # по часовой (True , +1), (False, +1), (True , -1), (False, -1)): # против часовой for i in range(matrix_size["H" if vertical else "W"] - 1): movements.append(((0 if vertical else 1) * step * increment, (1 if vertical else 0) * step * increment)) def move(pos=0): if work: c.move(oval, *movements[pos]) root.after(int(sleep*1000), lambda: move( (pos+1) % len(movements) )) def start(event): global work if not work: work = True move() def stop(): global work work = False c.coords(oval, offset, offset, offset + oval_size, offset + oval_size) #Заполнение матрицы for x in range(6): for y in range(6): text=c.create_text(30+60*x, 30+60*y, text=str(random.randint(0,99))) c.bind('<Double-Button-1>', start) menu=Menu(root) root.config(menu=menu) menu.add_command(label="Stop", command=stop) root.mainloop()
python — Как выйти из двух вложенных циклов
Ищу циклом текущего пользователя компьютера в локальной сети
def scan_Lan(): ip_list = ['192.168.4.'] i = 50 while i <= 240: scan_ip = ip_list[0] + str(i) response = subprocess.Popen(["ping", "-n", "1", "-w", "200", scan_ip]).wait() if(response == 0): try: wql = 'SELECT * FROM Win32_computerSystem' c = wmi. WMI(scan_ip, user='office\admin', password='fff') for item in c.query(wql): currentUser = str(item.UserName) print(currentUser) if(currentUser == "ivanov"): print(scan_ip) break except: print("-") i += 1 print("end") scan_Lan()
Все хорошо работает, но хочу после поиска выходить полностью из цикла while, как это сделать? Поставил вот здесь
print(scan_ip) break
но он по всей видимости выходит только из for, а как сделать глобальный break?
- python
- python-3.x
1
break
прекращает только вложенный цикл. Внешний цикл продолжает работать. Используйте return
, когда результат найден в вашем случае:
if current_user == 'ivanov': return scan_ip
Можно сделать так
while i <= 240: scan_ip = ip_list[0] + str(i) response = subprocess. Popen(["ping", "-n", "1", "-w", "200", scan_ip]).wait() if(response == 0): try: wql = 'SELECT * FROM Win32_computerSystem' c = wmi.WMI(scan_ip, user='office\admin', password='fff') for item in c.query(wql): currentUser = str(item.UserName) print(currentUser) if(currentUser == "ivanov"): print(scan_ip) break else: i += 1 # сюда зайдет, если цикл завершился полностью(то есть не было найдено) print("end") continue; except: print("-") break; # сюда попадем и прервем большой цикл, если во внутреннем был найден объект
Вот более простой пример для понимания
for x in xrange(10): for y in xrange(10): for z in xrange(10): print x,y,z if x*y*z == 30: break # прерываем внутренний цикл else: continue # продолжаем, если внутренний цикл не был прерван break # внутренний цикл был прерван, прерываем и этот цикл else: continue break
Используйте флаг (булево значение) для выхода из циклов. При входе в условие currentUser == «ivanov» меняйте его значение на положительное, делайте break, а в основном цикле установите условие while i <= 240 and not result, тогда цикл будет завершен, как только result станет истиной.
Глобального break, для выхода из всех циклов, не существует.
a:
list_ = [1, 2, 3, 4, 5] check = True while check: for v in list_: if v == 3: check = False break else: print(v)
b:
list_ = [1, 2, 3, 4] try: while True: for v in list_: if v == 3: raise UserWarning else: print(v) except UserWarning:pass
1
2
Зарегистрируйтесь или войдите
Регистрация через Google
Регистрация через Facebook
Регистрация через почту
Отправить без регистрации
Почта
Необходима, но никому не показывается
Отправить без регистрации
Почта
Необходима, но никому не показывается
Нажимая на кнопку «Отправить ответ», вы соглашаетесь с нашими пользовательским соглашением, политикой конфиденциальности и политикой о куки
Python выйти из цикла раньше –
спросил
Изменено 11 лет, 4 месяца назад
Просмотрено 65 тысяч раз
Как выйти из цикла раньше в Python?
для а в б: если критерии в списке1: печатать "о нет" #Принудительный цикл, т. е. форсировать следующую итерацию, не продолжая someList.append(a)
Кроме того, в Java вы можете вырвать
из цикла, есть ли эквивалент в Python?
- питон
- петли
1
продолжить
и прервать
то, что вы хотите. В этом отношении Python работает идентично Java/C++.
1
Во-первых, имейте в виду, что с пониманием списка можно делать то, что вы хотите. Таким образом, вы можете использовать что-то вроде:
somelist = [a для a в b, если не a.criteria в otherlist]
Если вы хотите раньше выйти из цикла в Python, вы можете использовать break
, как и в Java.
>>> для x в xrange(1,6): ... напечатать х ... если х == 2: ... сломать ... 1 2
Если вы хотите начать следующую итерацию цикла раньше, используйте continue
, опять же, как в Java.
>>> для x в xrange(1,6): ... если х == 2: ... Продолжить ... напечатать х ... 1 3 4 5
Вот документация для break
и continue
. Это также охватывает else
предложений для циклов, которые не запускаются, когда вы прерываете
.
continue
и break
работают точно так же, как и в других языках программирования, за исключением того, что вы не можете разбить
на метку (как, например, в Java). Это означает, что вы можете разорвать только один цикл за раз.
Взгляните на перерыв
и продолжить
.
Зарегистрируйтесь или войдите в систему
Зарегистрируйтесь с помощью Google
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя электронную почту и пароль
Опубликовать как гость
Электронная почта
Требуется, но никогда не отображается
Опубликовать как гость
Электронная почта
Требуется, но не отображается
python — Как я могу остановить цикл While?
Задать вопрос
спросил
Изменено 13 дней назад
Просмотрено 245 тысяч раз
Я написал цикл while
в функции, но не знаю, как его остановить. Когда он не соответствует своему конечному условию, цикл просто продолжается вечно. Как я могу это остановить?
определение_периода (вселенная_массива): период=0 tmp=universe_array пока верно: tmp=apply_rules(tmp)#aplly_rules — это другая функция период+=1 если numpy.array_equal(tmp,universe_array) имеет значение True: break #я хочу, чтобы цикл останавливался и возвращал 0, если #период больше 12 если период>12: # я написал эту строку, чтобы остановить его.. но кажется, что это #не работает....помогите.. вернуть 0 еще: период возврата
- питон
- цикл while
4
просто сделайте правильный отступ в коде:
def define_period(universe_array): период=0 tmp=universe_array пока верно: tmp=apply_rules(tmp)#aplly_rules — это другая функция период+=1 если numpy. array_equal(tmp,universe_array) имеет значение True: период возврата если период>12: # я написал эту строку, чтобы остановить его.. но, похоже, это не работает.... помогите.. вернуть 0 еще: период возврата
Вы должны понимать, что оператор break
в вашем примере выйдет из бесконечного цикла, который вы создали с помощью , в то время как True
. Поэтому, когда условие прерывания равно True, программа выйдет из бесконечного цикла и перейдет к следующему блоку с отступом. Поскольку в вашем коде нет следующего блока, функция завершается и ничего не возвращает. Итак, я исправил ваш код, заменив оператор break
оператором return
.
Следуя вашей идее использовать бесконечный цикл, это лучший способ написать его:
определение_периода (вселенная_массива): период=0 tmp=universe_array пока верно: tmp=apply_rules(tmp)#aplly_rules — это другая функция период+=1 если numpy. array_equal(tmp,universe_array) имеет значение True: сломать если период>12: # я написал эту строку, чтобы остановить его.. но, похоже, это не работает.... помогите.. период = 0 сломать период возврата
3
определение_периода (вселенная_массива): период=0 tmp=universe_array в то время как период <12: tmp=apply_rules(tmp)#aplly_rules — это другая функция если numpy.array_equal(tmp,universe_array) имеет значение True: сломать период+=1 период возврата
5
Оператор is
в Python, вероятно, не делает того, что вы ожидаете. Вместо этого:
, если numpy.array_equal(tmp,universe_array) имеет значение True: сломать
Я бы написал так:
if numpy.array_equal(tmp,universe_array): сломать
— это оператор
, проверяющий идентичность объекта, что совсем не похоже на равенство.