Основы языка Dart
Входной точкой в программу на языке Dart является функция main . Именно с нее начинается выполнение программы. Она обязательно должна присутствовать в программе. Ее простейшее определение может быть следующим:
void main()
Слово void вначале определения функции указывает, что она не возвращает никакого значения, просто выполняет некоторые действия. Далее идет собственно имя функции — main и затем пустые скобки, которые указывают, что функция не принимет параметров. Хотя мы также можем использовать и другую форму функции main, которая принимает параметры — и через эти параметры передать функции данные извне при запуске программы.
После пустых скобок идет блок функции в виде открывающей и закрывающей фигурных скобок <>, внутри которых помещается набор выполняемых инструкций — те действия, которые и будет выполнять программа.
Инструкции (statement) являются основным строительным блоком в программе на Dart. Каждая инструкция выполняет некоторое действие, например, вызовы методов, объявление переменных и присвоение им значений. После завершения инструкции в Dart ставится точка с запятой (;). Данный знак указывает на конец инструкции. Например:
print("Hello Dart!");
Данная строка представляет вызов функции print , которая выводит на консоль строку «Hello Dart!». В данном случае вызов функции является инструкцией и поэтому завершается точкой с запятой.
Кроме отдельных инструкций распространенной конструкцией является блок кода. Блок кода содержит набор инструкций, он заключается в фигурные скобки, а инструкции помещаются между открывающей и закрывающей фигурными скобками:
В этом блоке кода две инструкции, которые выводят на консоль определенную строку.
Функция main по сути также является блоком кода и также может содержать другие блоки кода:
void main() < < print("Hello!"); print("Welcome to Dart!"); >>
Комментарии
Код программы может содержать комментарии. Комментарии позволяют понять смыл программы, что делают те или иные ее части. При компиляции комментарии игнорируются и не оказывают никакого влияние на работу приложения и на его размер.
В Dart есть два типа комментариев: однострочный и многострочный. Однострочный комментарий размещается на одной строке после двойного слеша //. А многострочный комментарий заключается между символами /* текст комментария */ . Он может размещаться на нескольких строках. Например:
/* многострочный комментарий Первая программа на языке Dart */ // определение функции main void main () < // начало объявления функции print("Hello Dart!"); // вывод строки на консоль >// конец объявления функции
Входная точка в программу что это
Точка входа в программу представляет функцию, с которой начинается выполнение приложения. Для определения функции как точки входа в приложения, применяются ряд условий:
-
Эта функция должна применять атрибут []
Последний компилируемый файл — это последний файл в проекте, либо последний файл в списке файлов, которые передаются компилятору при компиляции в командной строке
[] let main argv = printfn "Начало выполнения приложения" 0
Итак, данная функция применяет атрибут [
[] let main _ = printfn "Начало выполнения приложения" 0
Теперь обратимся к последнему условию: функция входа в приложение должна быть последней функций (и вообще последним опредлением в файле). То есть мы можем разместить другие конструкции, определения значений, функций, их вызов до функции main:
let sum x y = x + y let message = "Hello F#" printfn $"" [] let main _ = printfn "Функция main" 0
Но мы НЕ можем это сделать после определения функции входа в приложение:
[] let main _ = printfn "Функция main" 0 let sum x y = x + y let message = "Hello F#" printfn $""
Но в принципе в этом случае Visual Studio укажет на ошибку. Стоит отметить, что если до функции точки входа в приложение идут вызовы других функций , то они также выполняются. В данном случае имеются ввиду вызовы функций верхнего уровня — то есть такие вызовы функций, которые расположены вне других функций. Например, путь у нас будет следующий код программы:
let sum x y = x + y let message = "Hello F#" printfn $"" printfn $"Сумма 1 и 2 равна " [] let main _ = printfn "Функция main" 0
В данном случае мы получим следующий консольный вывод:
Hello F# Сумма 1 и 2 равна 3 Функция main
Таким образом, мы видим, что все выражения, которые идут до функции main, также были выполнены. Однако если до функции входа в приложение идут только определения функций без их вызовов, то эти функции не выполняются:
let sum x y = printfn $"Сумма и равна " let printMessage _ = printfn "Hello F#" [] let main _ = printfn "Функция main" 0
Так, в данном случае будет выполняться только функция main, поскольку именно она является точкой входа в приложения. Соответственно консольный вывод программы:
Функция main
Чтобы выполнить подобные функции, нам надо вызвать их в функции main:
let sum x y = printfn $"Сумма и равна " let printMessage _ = printfn "Hello F#" [] let main _ = printfn "Функция main" sum 1 2 printMessage() 0
Консольный вывод программы:
Функция main Сумма 1 и 2 равна 3 Hello F#
Неявная точка входа
Выше было показано, как определять точку входа, однако в предыдущих статьях точка входа не использовалась, но код тем не менее выполнялся. Если в коде явным образом не определено функции с атрибутом EntryPoint , то в качестве точки входа используются все привязки значений и функций верхнего уровня, которые определены в последнем компилируемом файле.
Точка входа
В программах, написанных на Python часто можно увидеть такую конструкцию:
if __name__ == "__main__":
Это точка входа — место, с которого начинает выполняться ваша программа. Но какие еще значения может принимать переменная __name__ ? Зачем вообще нужна эта проверка?
Переменная __name__
Для начала, попробуем провести несколько экспериментов. Создадим папку с тремя файлами: my_module.py , calculations.py и processing.py . А теперь выведем на экран переменные __name__ каждого из этих файлов. В каждом случае результат будет одинаковым.
>>> __name__ '__main__' А теперь попробуем импортировать модули, и снова проверить значение их переменных `__name__`. ```pycon >>> import my_module >>> import calculations >>> my_module.__name__ my_module >>> calculations.__name__ calculations >>> .dir() [. '__name__', . 'calculations', 'my_module']
Как видите, переменная __name__ теперь содержит название файла импортированного модуля. Функция dir() в нашем случае возвращает глобальное пространство имен. В конце списка притаились те самые имена импортированных модулей. Теперь мы сможем обращаться к их содержимому через эти названия.
Точка входа
Давайте разберем работу типичной точки входа на примере файла processing.py .
import calculations import my_module def main(): while True: inp = input("Insert value:") converted = calculations.convert(inp) transformed = calculations.transform(converted) print(my_module.output(transformed)) if __name__ == "__main__": main()
Сначала интерпретатор импортирует модули, затем определяет функцию main() , и доходит до блока if __name__ == ‘__main__’: . Если пользователь непосредственно запустил файл processing.py , условие будет удовлетворено, и начнется выполнение функции main() . Пользователь сможет ввести какую-то строку в консоль, она будет обработана функциями из модулей calculations и my_module , а затем выведена на экран. Цикл будет повторяться, пока пользователь не завершит программу.
Но представьте себе, что мы решили сделать более сложную программу, которая использует те же функции. Чтобы не переписывать тот же самый код, мы импортировали processing.py . Если бы мы не проверяли значение переменной __name__ , функция main() запустилась бы при импорте. Программа застряла бы в одном бесконечном цикле while , а интерпретатор никогда не дошел бы до кода нашей новой программы.
>>> import processing Insert value:
Это было бы крайне нежелательно. Поэтому мы и проверяем содержимое переменной __name__ перед запуском функции main() . Поскольку при импорте ее содержимое меняется на название модуля — processing , то проверка не будет пройдена, и main() не запустится. Зато мы сможем использовать любые объекты импортированного модуля:
import processing mode = input('Mode:') if mode == 'standard': processing.main() else print(processing.my_module.output(input()))
Заключение
С точки входа начинается выполнение программы. Содержимое блока if __name__ == ‘__main__’: не выполняется, если файл импортирован, а не запущен напрямую. Это позволяет разместить в нем код, который помешал бы импорту содержимого модуля, но нужен при непосредственном доступе. Использование этой конструкции — хорошая практика, которая поможет избежать проблем при импорте вашего модуля.
Практический Python для начинающих
Станьте junior Python программистом за 7 месяцев
При подготовке материала использовались источники:
https://metanit.com/dart/tutorial/2.1.php
https://metanit.com/f/tutorial/2.9.php
https://pylot.me/article/38-tochka-vhoda/