Перейти к содержанию

Поток управления

Mojo включает в себя несколько традиционных структур потока управления для условного и повторного выполнения блоков кода.

Оператор if

Mojo поддерживает оператор if для выполнения условного кода. С его помощью вы можете условно выполнить блок кода с отступом, если значение данного логического выражения равно True.

temp_celsius = 25
if temp_celsius > 20:
    print("It is warm.")
    print("The temperature is", temp_celsius * 9 / 5 + 32, "Fahrenheit." )
It is warm.
The temperature is 77.0 Fahrenheit.

Вы можете записать весь оператор if в виде одной строки, если все, что вам нужно для условного выполнения, - это один короткий оператор.

temp_celsius = 22
if temp_celsius < 15: print("It is cool.") # Skipped because condition is False
if temp_celsius > 20: print("It is warm.")
It is warm.

Опционально, оператор if может включать любое количество дополнительных предложений elif, каждое из которых определяет логическое условие и связанный с ним блок кода для выполнения в случае True. Условия проверяются в указанном порядке. Когда условие оценивается как True, соответствующий блок кода выполняется и никакие другие условия не проверяются.

Кроме того, оператор if может включать необязательное предложение else, предоставляющее блок кода для выполнения, если все условия оцениваются как False.

temp_celsius = 25
if temp_celsius <= 0:
    print("It is freezing.")
elif temp_celsius < 20:
    print("It is cool.")
elif temp_celsius < 30:
    print("It is warm.")
else:
    print("It is hot.")
It is warm.

TODO

В настоящее время Mojo не поддерживает эквивалент оператора Python match или C switch для сопоставления с шаблоном и условного выполнения.

Вычисления по короткой схеме

Mojo придерживается семантики вычисления по короткой схеме для логических операторов. Если первый аргумент оператора or принимает значение True, второй аргумент не вычисляется.

def true_func() -> Bool:
    print("Executing true_func")
    return True

def false_func() -> Bool:
    print("Executing false_func")
    return False

print('Short-circuit "or" evaluation')
if true_func() or false_func():
    print("True result")
Short-circuit "or" evaluation
Executing true_func
True result

Если первый аргумент оператора and принимает значение False, то второй аргумент не вычисляется.

print('Short-circuit "and" evaluation')
if false_func() and true_func():
    print("True result")
Short-circuit "and" evaluation
Executing false_func

Условные выражения

Mojo также поддерживает условные выражения (или то, что иногда называют троичным условным оператором), используя синтаксис true_result if boolean_expression else false_result, как и в Python. Чаще всего это используется как краткий способ присвоения переменной одного из двух разных значений на основе логического условия.

temp_celsius = 15
forecast = "warm" if temp_celsius > 20 else "cool"
print("The forecast for today is", forecast)
The forecast for today is cool

Альтернативный вариант, записанный в виде многострочного оператора if, более подробен.

if temp_celsius > 20:
    forecast = "warm"
else:
    forecast = "cool"
print("The forecast for today is", forecast)
The forecast for today is cool

Оператор while

Цикл while многократно выполняет блок кода, в то время как значение данного логического выражения равно True. Например, следующий цикл выводит значения из ряда Фибоначчи, которые меньше 50.

fib_prev = 0
fib_curr = 1

print(fib_prev, end="")
while fib_curr < 50:
    print(",", fib_curr, end="")
    fib_prev, fib_curr = fib_curr, fib_prev + fib_curr
0, 1, 1, 2, 3, 5, 8, 13, 21, 34

Оператор continue пропускает выполнение остальной части блока кода и возобновляет его с помощью тестового выражения цикла.

n = 0
while n < 5:
    n += 1
    if n == 3:
        continue
    print(n, end=", ")
1, 2, 4, 5,

Оператор break завершает выполнение цикла.

n = 0
while n < 5:
    n += 1
    if n == 3:
        break
    print(n, end=", ")
1, 2,

Опционально, цикл while может включать предложение else. Тело предложения else выполняется, когда логическое условие цикла принимает значение False, даже если оно выполняется при первом тестировании.

n = 5

while n < 4:
    print(n)
    n += 1
else:
    print("Loop completed")
Loop completed

Предложение else не выполняется, если оператор break или return завершает цикл while.

n = 0
while n < 5:
    n += 1
    if n == 3:
        break
    print(n)
else:
    print("Executing else clause")
1
2

Оператор for

Цикл for выполняет итерацию по последовательности, выполняя блок кода для каждого элемента в последовательности. Цикл Mojo for может выполнять итерацию по любому типу, реализующему метод __iter__(), который возвращает тип, определяющий методы __next__() и __len__().

Обход коллекций Mojo

Все типы коллекций в модуле collections поддерживают циклическую итерацию. Смотрите документацию по типам коллекций для получения дополнительной информации о типах коллекций Mojo.

Ниже показан пример итерации по списку Mojo.

states = ["California", "Hawaii", "Oregon"]
for state in states:
    print(state)
California
Hawaii
Oregon

Тот же метод работает и для перебора Set Mojo.

from collections import Set

values = {42, 0}
for item in values:
    print(item)
42
0

Существует два метода итерации по Mojo Dict. Первый - это итерация непосредственно с использованием Dict, которая создает последовательность ключей словаря.

var capitals: Dict[String, String] = {
    "California": "Sacramento",
    "Hawaii": "Honolulu",
    "Oregon": "Salem"
}

for var state in capitals:
    print(capitals[state] + ", " + state)
Sacramento, California
Honolulu, Hawaii
Salem, Oregon

Второй подход к итерации по Mojo Dict заключается в вызове его метода items(), который создает последовательность объектов DictEntry. В теле цикла вы можете получить доступ к полям ключа и значения записи.

for item in capitals.items():
    print(item.value + ", " + item.key)
Sacramento, California
Honolulu, Hawaii
Salem, Oregon

Обход с использованием ссылок

Другим типом итераций, предоставляемых стандартной библиотекой Mojo, является диапазон, который представляет собой последовательность целых чисел, сгенерированных функцией range(). Он отличается от типов коллекций, показанных выше, тем, что реализован как генератор, генерирующий каждое значение по мере необходимости, а не материализующий всю последовательность в памяти. Например:

var values = [1, 4, 7, 3, 6, 11]
for ref value in values:
    if value % 2 != 0:
        value -= 1
print(values.__str__())
[0, 4, 6, 2, 6, 10]

Обход ranges

Другим типом итераций, предоставляемых стандартной библиотекой Mojo, является диапазон, который представляет собой последовательность целых чисел, сгенерированных функцией range(). Он отличается от типов коллекций, показанных выше, тем, что реализован как генератор, генерирующий каждое значение по мере необходимости, а не материализующий всю последовательность в памяти. Например:

for i in range(5):
    print(i, end=", ")
0, 1, 2, 3, 4,

Управление состояниями цикла for

Оператор continue пропускает выполнение остальной части блока кода и возобновляет цикл со следующим элементом коллекции.

for i in range(5):
    if i == 3:
        continue
    print(i, end=", ")
0, 1, 2, 4,

Оператор break завершает выполнение цикла.

for i in range(5):
    if i == 3:
        break
    print(i, end=", ")
0, 1, 2,

Необязательно, цикл for может включать предложение else. Основная часть предложения else выполняется после итерации по всем элементам коллекции.

for i in range(5):
    print(i, end=", ")
else:
    print("\nFinished executing 'for' loop")
0, 1, 2, 3, 4,
Finished executing 'for' loop

Предложение else выполняется, даже если коллекция пуста.

from collections import List

var empty: List[Int] = []
for i in empty:
    print(i)
else:
    print("Finished executing 'for' loop")
Finished executing 'for' loop

Предложение else не выполняется, если оператор break или return завершает цикл for.

from collections import List

animals = ["cat", "aardvark", "hippopotamus", "dog"]
for animal in animals:
    if animal == "dog":
        print("Found a dog")
        break
else:
    print("No dog found")
Found a dog

Итерация по коллекциям Python

Цикл Mojo for поддерживает итерацию по типам коллекций Python. Каждый элемент, извлекаемый циклом, является оболочкой PythonObject для объекта Python. Обратитесь к документации по типам Python для получения дополнительной информации о манипулировании объектами Python из Mojo.

Ниже приведен простой пример итерации по списку Python смешанного типа.

from python import Python

def main():
    # Создается список Python смешанного типа
    py_list = Python.list(42, "cat", 3.14159)
    for py_obj in py_list:  # Каждый элемент имеет тип "PythonObject"
        print(py_obj)
42
cat
3.14159

Существует два метода итерации по словарю Python. Первый - это итерация непосредственно с использованием словаря, который генерирует последовательность его ключей.

from python import Python

def main():
    # Create a mixed-type Python dictionary
    py_dict = Python.evaluate("{'a': 1, 'b': 2.71828, 'c': 'sushi'}")
    for py_key in py_dict:  # Each key is of type "PythonObject"
        print(py_key, py_dict[py_key])
a 1
b 2.71828
c sushi

Второй подход к итерации по словарю Python заключается в вызове его метода items(), который создает последовательность объектов из 2 кортежей. В теле цикла вы можете получить доступ к ключу и значению по индексу.

from python import Python

def main():
    # Create a mixed-type Python dictionary
    py_dict = Python.evaluate("{'a': 1, 'b': 2.71828, 'c': 'sushi'}")
    for py_tuple in py_dict.items():  # Each 2-tuple is of type "PythonObject"
        print(py_tuple[0], py_tuple[1])
a 1
b 2.71828
c sushi