Вот что происходит.
Во-первых, единственные глобальные переменные, которые действительно есть в Python, - это переменные в области видимости модуля. Вы не можете сделать переменную действительно глобальной; все, что вы можете сделать, это создать переменную в определенной области. (Если вы создаете переменную внутри интерпретатора Python, а затем импортируете другие модули, ваша переменная находится во внешней области видимости и, следовательно, глобальна в вашем сеансе Python.)
Все, что вам нужно сделать, чтобы создать глобальную переменную модуля, - это просто присвоить имя.
Представьте себе файл с именем foo.py, содержащий эту единственную строку:
X = 1
А теперь представьте, что вы его импортируете.
import foo
print(foo.X) # prints 1
Однако предположим, что вы хотите использовать одну из переменных в области модуля как глобальную внутри функции, как в вашем примере. По умолчанию Python предполагает, что переменные функции являются локальными. Вы просто добавляете объявление global в свою функцию, прежде чем пытаться использовать global.
def initDB(name):
global __DBNAME__ # add this line!
if __DBNAME__ is None: # see notes below; explicit test for None
__DBNAME__ = name
else:
raise RuntimeError("Database name has already been set.")
Между прочим, для этого примера достаточно простого if not __DBNAME__ теста, потому что любое строковое значение, кроме пустой строки, будет оценивать как истину, поэтому любое фактическое имя базы данных будет оценивать как истину. Но для переменных, которые могут содержать числовое значение, которое может быть 0, вы не можете просто сказать if not variablename; в этом случае вы должны явно проверить None с помощью оператора is. Я изменил пример, добавив явный None тест. Явный тест для None никогда не ошибается, поэтому я по умолчанию использую его.
Наконец, как другие отмечали на этой странице, два ведущих подчеркивания сигнализируют Python о том, что вы хотите, чтобы переменная была «частной» для модуля. Если вы когда-нибудь сделаете import * from mymodule, Python не будет импортировать имена с двумя ведущими символами подчеркивания в ваше пространство имен. Но если вы просто выполните простой import mymodule, а затем произнесете dir(mymodule), вы увидите «частные» переменные в списке, а если вы явно ссылаетесь на mymodule.__DBNAME__ Python, это не заботит, он просто позволит вам ссылаться на них. Двойное подчеркивание в начале является основным ключом к пониманию пользователей вашего модуля, что вы не хотите, чтобы они привязывали это имя к какому-либо собственному значению.
В Python считается лучшей практикой не делать import *, а минимизировать взаимосвязь и максимизировать явность, используя mymodule.something или явно выполняя импорт, например from mymodule import something.
РЕДАКТИРОВАТЬ: Если по какой-то причине вам нужно сделать что-то подобное в очень старой версии Python, в которой нет ключевого слова global, есть простой обходной путь. Вместо того, чтобы напрямую устанавливать глобальную переменную модуля, используйте изменяемый тип на глобальном уровне модуля и сохраните свои значения внутри него.
В ваших функциях имя глобальной переменной будет доступно только для чтения; вы не сможете повторно привязать фактическое имя глобальной переменной. (Если вы присвоите этой переменной имя внутри своей функции, это повлияет только на имя локальной переменной внутри функции.) Но вы можете использовать это имя локальной переменной для доступа к реальному глобальному объекту и хранения данных внутри него.
Вы можете использовать list, но ваш код будет некрасивым:
__DBNAME__ = [None] # use length-1 list as a mutable
# later, in code:
if __DBNAME__[0] is None:
__DBNAME__[0] = name
dict лучше. Но наиболее удобен экземпляр класса, и вы можете просто использовать тривиальный класс:
class Box:
pass
__m = Box() # m will contain all module-level values
__m.dbname = None # database name global in module
# later, in code:
if __m.dbname is None:
__m.dbname = name
(Вам действительно не нужно использовать переменную имени базы данных с заглавной буквы.)
Мне нравится синтаксический сахар простого использования __m.dbname, а не __m["DBNAME"]; На мой взгляд, это наиболее удобное решение. Но решение dict тоже работает нормально.
С dict вы можете использовать любое хешируемое значение в качестве ключа, но когда вас устраивают имена, которые являются действительными идентификаторами, вы можете использовать тривиальный класс, такой как Box из приведенного выше.
person
steveha
schedule
30.12.2009