Ответы:
Это не имеет ничего общего с Python; глобальные переменные плохо подходят для любого языка программирования.
Однако глобальные константы концептуально не то же самое, что глобальные переменные ; глобальные константы совершенно безвредны. В Python различие между ними чисто условное: CONSTANTS_ARE_CAPITALIZED
и globals_are_not
.
Причина, по которой глобальные переменные плохи, заключается в том, что они позволяют функциям иметь скрытые (неочевидные, неожиданные, трудно обнаруживаемые, трудно диагностируемые) побочные эффекты, ведущие к увеличению сложности, что может привести к спагетти-коду .
Однако разумное использование глобального состояния допустимо (как и локальное состояние и изменчивость) даже в функциональном программировании, либо для оптимизации алгоритмов, уменьшения сложности, кэширования и мемоизации, либо для практичности переноса структур, происходящих из преимущественно императивной кодовой базы.
В общем, на ваш вопрос можно ответить по-разному, поэтому лучше всего просто погуглить «почему глобальные переменные плохи». Некоторые примеры:
Если вы хотите глубже понять, почему возникают побочные эффекты, а также многое другое, вам следует изучить функциональное программирование:
Да теоретически глобалы (и «состояние» в целом) - зло. На практике, если вы заглянете в каталог пакетов python, вы обнаружите, что большинство модулей там начинаются с набора глобальных объявлений. Очевидно, у людей с ними нет проблем.
В частности, для python видимость глобальных объектов ограничена модулем, поэтому нет «настоящих» глобальных объектов, влияющих на всю программу, что делает их менее опасными. Еще один момент: их нет const
, поэтому, когда вам нужна константа, вы должны использовать глобальную.
В моей практике, если мне случится изменить глобальный объект в функции, я всегда объявляю его с помощью global
, даже если технически в этом нет необходимости, например:
cache = {}
def foo(args):
global cache
cache[args] = ...
Это упрощает отслеживание манипуляций глобальными объектами.
Личное мнение по этой теме заключается в том, что наличие глобальных переменных, используемых в логике функции, означает, что некоторый другой код может изменить логику и ожидаемый результат этой функции, что очень усложнит отладку (особенно в больших проектах) и затруднит тестирование. также.
Кроме того, если вы считаете, что другие люди читают ваш код (сообщество с открытым исходным кодом, коллеги и т. Д.), Им будет сложно понять, где устанавливается глобальная переменная, где были изменены и чего ожидать от этой глобальной переменной, а не от нее. изолированной функции, что ее функциональность может быть определена путем чтения самого определения функции.
Я считаю, что чистый и (почти) безошибочный код должен иметь максимально чистые функции (см. Чистые функции ). Чистая функция - это функция, удовлетворяющая следующим условиям:
Наличие глобальных переменных нарушает хотя бы одну из вышеперечисленных, если не обе, поскольку внешний код, вероятно, может привести к неожиданным результатам.
Другое четкое определение чистых функций: «Чистая функция - это функция, которая принимает все свои входные данные как явные аргументы и производит все свои выходные данные как явные результаты ». [1] . Наличие глобальных переменных нарушает идею чистых функций, поскольку вход и, возможно, один из выходов (глобальная переменная) явно не передаются или не возвращаются.
Далее , что, если вы считаете , юнит-тестирование и первый принцип ( F Аст испытания, I ndependent тесты, R epeatable, S эльфа-Validating и T imely) , вероятно , будет нарушать принцип независимых тестов (что означает , что тесты не зависят друг на друга).
Наличие глобальной переменной (не всегда), но в большинстве случаев (по крайней мере, из того, что я видел до сих пор) - это подготовка и передача результатов другим функциям. Это также нарушает этот принцип. Если глобальная переменная использовалась таким образом (т. Е. Глобальная переменная, используемая в функции X, должна быть сначала установлена в функции Y), это означает, что для функции модульного тестирования X вы должны сначала запустить функцию тестирования / запуска Y.
С другой стороны, и как уже упоминалось другими людьми, использование глобальной переменной в качестве «постоянной» может быть немного лучше, поскольку язык не поддерживает константы. Однако я всегда предпочитаю работать с классами и иметь «константы» в качестве члена класса и вообще не использовать глобальную переменную. Если у вас есть код, который требует, чтобы два разных класса разделяли глобальную переменную, вам, вероятно, потребуется реорганизовать решение и сделать классы независимыми.
Я не считаю, что использовать глобальные переменные нельзя. Но если они используются, авторам следует рассмотреть некоторые принципы (возможно, упомянутые выше, а также другие принципы и передовые методы разработки программного обеспечения) для более чистого и почти безошибочного кода.
Они необходимы, и экран тому хороший тому пример. Однако в многопоточной среде или с участием большого количества разработчиков на практике часто возникает вопрос: кто (ошибочно) установил или очистил его? В зависимости от архитектуры анализ может быть дорогостоящим и часто требоваться. Хотя чтение глобальной переменной может быть нормальным, запись в нее должна контролироваться, например, одним потоком или потокобезопасным классом. Следовательно, глобальные вары вызывают страх перед высокими затратами на разработку, возможными из-за последствий, которые сами по себе считаются злом. Поэтому в целом рекомендуется поддерживать низкое количество глобальных переменных.
eval
,import *
, конкатенация , переменномid
, тень атрибутов )