Изменить тип глобальной переменной в функции, инициализирующей ее - PullRequest
0 голосов
/ 24 февраля 2010

У меня есть функция __main__, где я инициализирую множество переменных, которые позже будут использоваться в моей программе. У меня есть проблема, когда переменной, которую я временно объявляю как None во внешней области видимости, присваивается объект SomeClass, но из-за правил области видимости я не могу получить доступ к ее содержимому во внешней области видимости. Поскольку конструктор SomeClass требует передачи аргумента, я не могу просто объявить myObject равным foo.bar.SomeClass для начала. Итак, что я должен сделать, чтобы получить доступ к атрибутам в foo.bar.SomeClass?

Codewise это выглядит так:

myObject = None

def setUp():
    ... lots of initialization ...
    myObject = foo.bar.SomeClass(init_variable)

if __name__ == "__main__":
    setUp()
    myObject.member1 #throws AttributeError: 'NoneType' object has no attribute member1

Ответы [ 3 ]

2 голосов
/ 24 февраля 2010

Вам не обязательно делать это - использование глобалов считается плохой практикой для большинства применений.Вы всегда можете вернуть нужные данные:

def initialize():
    ... lots of initialization ...
    return foo.bar.SomeClass(init_variable)

if __name__ == "__main__":
    myObject = initialize()
    myObject.member1 # works

РЕДАКТИРОВАТЬ: если вам нужно инициализировать несколько значений или если вы видите, что используете слишком много глобальных переменных для совместного использования состояния между многими функциями верхнего уровня, тогдапора использовать class.

class MyProgram(object):
    def __init__(self):
        # ... lots of initialization ...
        self.myObject = foo.bar.SomeClass(init_variable)

    def usage(self):
        self.myObject.member1

if __name__ == "__main__":
    m = MyProgram()
    m.usage()
2 голосов
/ 24 февраля 2010

Если предположить, что setup() означает initialize(), проблема в том, что переменная myObject в initialize() является локальной переменной, которая скрывает глобальную myObject, а когда initialize() возвращает, локальная переменная имя выйдет за рамки.

Чтобы обновить глобальную переменную myObject, вам нужно изменить initialize() следующим образом:

def initialize():
    global myObject
    ... lots of initialization ...
    myObject = foo.bar.SomeClass(init_variable)

Добавление оператора global означает, что глобальный myObject обновляется, а не локальный.

0 голосов
/ 24 февраля 2010

Если вашему SomeClass требуется аргумент от выполнения скрипта, вероятно, будет проще всего передать любую информацию, которая вам понадобится, чтобы создать его экземпляр в качестве аргумента. Это может выглядеть примерно так:

def initialize(args):
    ... lots of initialization ...
    myObject = foo.bar.SomeClass(args[0])

if __name__ == "__main__":
    initialize(sys.argv)

Еще один способ сделать это - сделать глобальный экземпляр myObject с помощью ключевого слова global перед вызовом initialize().

.
...