Одна из тех приятных особенностей Python , которая помечает его как язык, разработанный для разработчиков (в отличие от языка, разработанного для поставщиков инструментов), — это возможность условно запускать некоторую логику, если вы выполняете скрипт напрямую, но игнорировать его, если скрипт импортируется («включается») другим скриптом.
Например;
class User: def setName(self, name): self.name = name def getName(self): return self.name # Only execute this we're "main"... if __name__ == "__main__": u = User() u.setName("Harry") print u.getName()
class User: def setName(self, name): self.name = name def getName(self): return self.name # Only execute this we're "main"... if __name__ == "__main__": u = User() u.setName("Harry") print u.getName()
Код после ‘if __name__ == “__main__”:’ выполняется только, если я запускаю этот скрипт напрямую. Если я импортирую класс User из другого скрипта, он игнорируется.
Создает очень удобный инструмент для тестирования (или еще лучше модульного тестирования) скрипта Python. Так сильно, что я хочу это в PHP.
Один из способов сделать это — вот так;
name = $name; } function getName() { return $this->name; } }
name = $name; } function getName() { return $this->name; } }
if (realpath (__ FILE__) == realpath ($ _ SERVER [‘SCRIPT_FILENAME’])) {
$ u = & новый пользователь ();
$ U-> SetName ( «Гарри»);
print $ u-> getName ();
}
?>
Это зависит от предопределенной константы __FILE__, которая заполняется именем скрипта, к которому осуществляется доступ к __FILE__ (т.е. она работает независимо от включений). Насколько я знаю, значение __FILE__ должно быть уникальным для скрипта.
Здесь есть две проблемы. Во-первых, если вы используете этот подход очень часто, то к realpath () будет приложено множество вызовов, что означает снижение производительности. Также $ _SERVER [‘SCRIPT_FILENAME’] возвращает имя исполняемого файла PHP при использовании PHP через CGI, и в противном случае, вероятно, нельзя полагаться на веб-серверы, кроме Apache.
Другой подход состоит в том, чтобы условно определить константу, используя значение __FILE__ eg;
class User { // .... }
if (!fined (‘__ MAIN__’)) {
define (‘__MAIN __’, __ FILE__);
}
if (__FILE__ == __MAIN__) {
$ u = & новый пользователь ();
$ U-> SetName ( «Гарри»);
print $ u-> getName ();
}
Если константа __MAIN__ еще не была определена (с помощью сценария, который включил этот), ей присваивается значение __FILE__ и выполняется блок условного кода.
Этот подход, вероятно, наиболее заслуживает доверия в том смысле, что он должен работать при любой установке PHP, но требует дополнительной работы, и если вы забудете определить где-то __MAIN__, вы можете получить исполняемый код, который вы не ожидали.
Обратите внимание, что следующее;
@define ('__MAIN__',__FILE__);
Оператор @ , используемый для подавления уведомления об ошибке, если __MAIN__ уже был определен, медленнее, чем использование is_defined () .
Третий вариант, который я не уверен, что я на 100% доверяю, чтобы работать везде правильно, это использовать get_included_files () like;
class User { // ... }
if (__FILE__ == array_shift (get_included_files ())) {
$ u = & новый пользователь ();
$ U-> SetName ( «Гарри»);
print $ u-> getName ();
}
Это основано на предположениях, что файл, с которого началось выполнение, всегда будет первым элементом в списке, возвращаемом get_included_files () (что, насколько я знаю, должно быть), и что он будет соответствовать значению __FILE__. Пока этот скрипт не был включен (или не требуется) любым другим, код внутри условия if выполняется.
Конечно, общий подход требует затрат на анализ кода внутри условия, чего можно избежать только с помощью кеша OPCODE, такого как Zend Accelerator, но это полезный инструмент, когда вы создаете модульный код и хотите разрабатывать и тестировать «модули». в вашем приложении без запуска всего приложения.