2016-02-13 4 views
3

Предположим, вы запускаете ракету. Когда вы поднимаетесь, вам нужно зафиксировать угол в соответствии с данной таблицей. Однако в определенные моменты вам нужно выполнить одноразовые действия (например, освобождение ускорителей, если они пустые, или отбрасывающие обтекатели на определенной высоте).Каков наилучший способ реализации конструкции `` `Python?

Что я делаю сейчас:

fairing_jettisoned = False 
while apogee < TARGET_APOGEE: 
    aim_rocket(speed, altitude, apogee) 
    if not fairing_jettisoned and altitude > FAIRING_ALT: 
     jettison_fairing() 
     fairing_jettisoned = True 

Это становится очень утомительным с более сложными рутин, потому что вы должны вернуться назад и вперед.

Другие языки имеют оператор when (when altitude > FAIRING_ALT:), но этого не существует в Python.

Один из способов, которым я пытался реализовать это с классами. Это Hacky, но это, кажется, работает хорошо:

class when(object): 
    calls = {} 
    def __init__(self, expr, func, *args, runs_left=1, **kwargs): 
     _, fname, line, *_ = inspect.stack()[1] 
     stored_instance = when.calls.get((fname, line), self) 
     if stored_instance == self: 
      self.func = func 
      self.args = args 
      self.kwargs = kwargs 
      self.runs_left = runs_left 
      when.calls[(fname, line)] = self 
     self = stored_instance 
     self.expr = expr 
     if self.runs_left and self.expr: 
      self.runs_left -= 1 
      return self.func(*self.args, **self.kwargs 

Это можно выполнить следующим образом:

while apogee < TARGET_APOGEE: 
    aim_rocket(speed, altitude, apogee) 
    when(altitude > FAIRING_ALT, jettison_fairing) 

В конце концов, что я хотел бы это иметь такой синтаксис:

while apogee < TARGET_APOGEE: 
    aim_rocket(speed, altitude, apogee) 
    when(altitude > FAIRING_ALT, runs_left=3): 
     # Do a bunch of things; no need for a lambda or function. 
     jettison_fairing() 

Я также попытался реализовать его с помощью __enter__ и __exit__, но я не мог найти способ пропустить до __exit__, если он уже запущен. Возможно ли это с помощью async/wait? Или это для чего-то совершенно другого?

+0

Это кажется немного лишним, почему бы просто не использовать логическое значение, которое изменяется при выполнении оператора if, являющегося условием оператора if? –

+1

Вот что я сейчас делаю. Либо bool, либо декрементный счетчик. Но переполнение вверх и вниз в коде очень утомительно, поэтому я подумал, есть ли лучший способ реализовать это. –

+0

Хорошо, если то, что вы делаете в данный момент с этим кодом, функционирует, тогда это кажется хорошим решением. Что касается реализации его как ключевого слова, вам придется написать свою собственную версию Python (путем внесения изменений в CPython), который, по моему мнению, определенно * не стоит вашего времени. –

ответ

1

Вы можете попробовать установить что-то с помощью нитей, например:

from threading import Thread 
import time, random 

def when(condition, action) -> Thread: 
    def threadtask(): 
     while not condition(): 
      time.sleep(0.5) 
     action() 
    t = Thread(target = threadtask) 
    t.start() 
    return t 

altitude = 1 
def jettison_fairing(): 
    print("Jettison the fairing!") 
when(lambda: altitude > 500, jettison_fairing) 
while altitude < 1000: 
    time.sleep(1) 
    altitude += random.randint(0,300) 
    print("Altitude is now ",altitude) 

# Output: 

##Altitude is now 173 
##Altitude is now 290 
##Altitude is now 370 
##Altitude is now 395 
##Altitude is now 464 
##Altitude is now 564 
##Jettison the fairing! 
##Altitude is now 736 
##Altitude is now 762 
##Altitude is now 1057 

Для бонусных очков, вы могли бы написать декоратор, который делает это.

Однако. То, что вы описываете, - это некоторые проблемы, с которыми сталкиваются программирование real-time systems. Там нет легкой конструкции «когда», которая решит вашу проблему. Что означает «когда» для вас - например, как часто программа проверяет высоту? Если ваша программа одновременно ждет пятидесяти различных условий «когда», являются ли они более приоритетными? Что произойдет, если два условия «когда» произойдут одновременно, а один комплект кода говорит компьютеру о выбросе обтекателя, а другой предполагает, что он все еще там?

Смежные вопросы