Статьи

Python __name__ == __main__ в PHP

Одна из тех приятных особенностей 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, но это полезный инструмент, когда вы создаете модульный код и хотите разрабатывать и тестировать «модули». в вашем приложении без запуска всего приложения.