Ответ 1
В С++ существует известная проблема, называемая фиаско порядка инициализации глобальной/статической переменной, из-за невозможности С++ решить, какая глобальная/статическая переменная будет инициализирована сначала в единицах компиляции,
Я думаю, что этот оператор подчеркивает ключевое различие между Python и С++: в Python нет таких вещей, как разные единицы компиляции. Я имею в виду, что на С++ (как вы знаете) два разных исходных файла могут быть скомпилированы полностью независимо друг от друга, и, таким образом, если вы сравните строку в файле A и строку в файле B, вам нечего сказать вы, который будет размещен первым в программе. Это похоже на ситуацию с несколькими потоками: вы не можете сказать, будет ли конкретный оператор в потоке 1 выполняться до или после определенного оператора в потоке 2. Можно сказать, что программы на С++ скомпилированы параллельно.
Напротив, в Python выполнение начинается в начале одного файла и выполняется в определенном порядке через каждый оператор в файле, разветвляясь на другие файлы в точках, где они импортируются. Фактически, вы могли бы почти думать о директиве import
как #include
, и таким образом вы могли бы определить порядок выполнения всех строк кода во всех исходных файлах программы. (Ну, это немного сложнее, потому что модуль действительно выполняется только при первом импорте и по другим причинам.) Если С++-программы скомпилированы параллельно, программы Python интерпретируются последовательно.
В вашем вопросе также затрагивается более глубокое значение модулей в Python. Модуль Python - это все, что находится в одном файле .py
, - это фактический объект. Все объявленное в "глобальной" области в одном исходном файле фактически является атрибутом этого объекта модуля. В Python нет истинной глобальной области. (Программисты Python часто говорят "глобальные", и на самом деле есть ключевое слово global
на языке, но оно всегда действительно относится к верхнему уровню текущего модуля.) Я мог видеть, что это немного странная концепция, чтобы получить используется для перехода с фона С++. Для меня потребовалось некоторое время, чтобы перейти от Java, и в этом отношении Java намного больше похожа на Python, чем на С++. (В Java также нет глобальной области)
Я упомянул, что в Python совершенно нормально использовать переменную без понятия, была ли она инициализирована/определена или нет. Ну, может быть, это не нормально, но, по крайней мере, приемлемо при соответствующих обстоятельствах. В Python попытка использовать переменную undefined вызывает a NameError
; вы не получаете произвольного поведения, как вы могли бы на C или С++, поэтому вы можете легко справиться с ситуацией. Вы можете увидеть этот шаблон:
try:
duck.quack()
except NameError:
pass
который ничего не делает, если duck
не существует. На самом деле, что вы чаще будете видеть,
try:
duck.quack()
except AttributeError:
pass
который ничего не делает, если duck
не имеет метода с именем quack
. (AttributeError
является той ошибкой, которую вы получаете, когда пытаетесь получить доступ к атрибуту объекта, но у объекта нет никакого атрибута по этому имени.) Это то, что проходит для проверки типа в Python: мы полагаем, что if все, что нам нужно, чтобы сделать утку, - это шарлатанство, мы можем просто попросить ее крякать, и если это произойдет, нам все равно, действительно ли это утка или нет. (Он называл утиную печать, -)