В функции Python atexit строки, установленные внутри функции, не видны? - PullRequest
0 голосов
/ 02 апреля 2020

Вчера я столкнулся (как мне кажется) с необычной проблемой области видимости при atexit в Python 2.7.10 (хотя проблема также в Python 3). Кажется, что глобальная строка, установленная внутри функции, не видна моей функции atexit, тогда как глобальные списки в порядке. Я уменьшил проблемный случай до этого:

import atexit

myString1 = None
myString2 = None
myArray1 = []
myArray2 = []

def setString1(newString):
    myString1 = newString

def setArray1(newString):
    myArray1.append(newString)

def testFinishUp():
    print("myString1 = " + str(myString1))
    print("myString2 = " + str(myString2))
    print("myArray1  = " + str(myArray1))
    print("myArray2  = " + str(myArray2))

setString1("Hello")
myString2 = "World"
setArray1("HELLO")
myArray2.append("WORLD")
atexit.register(testFinishUp)

Что это за выходные данные:

myString1 = None
myString2 = World
myArray1  = ['HELLO']
myArray2  = ['WORLD']

Теперь я уверен, что есть логическая причина, связанная с областью применения myString1. не ведет себя так же, как все остальные, но я, например, не вижу, что это такое. : - (

Кто-нибудь может объяснить, пожалуйста, что здесь происходит? Спасибо!

Ответы [ 2 ]

2 голосов
/ 02 апреля 2020

В этом нет ничего странного. Ваша проблема в том, что это утверждение:

Глобальная строка, заданная внутри функции, кажется невидимой для моей функции atexit, тогда как глобальные списки в порядке.

- ложь , Вы не устанавливаете глобальную строку внутри функции. Вместо этого вы создаете его локальную версию внутри области действия функции, которая скрывает глобальную. Если вы действительно хотите изменить глобальное значение, вы должны сделать следующее:

def setString1(newString):
    global myString1
    myString1 = newString

Причина, по которой он работает для ваших списков, заключается в том, что вы изменяете их на месте (через append) вместо создания копировать. Если бы вместо этого вы сделали

def setArray1(newString):
    myArray1 = myArray1 + [newString]

, вы бы увидели то же поведение, что и в строковом регистре.

Предупреждение: изменение глобального состояния из функций часто считается плохим стилем, так как он запутывает, где установлены значения. Обычно лучше изменить значения в глобальной области видимости, например, присваивая результат вызова функции.

0 голосов
/ 02 апреля 2020

Если вы хотите манипулировать глобальной неизменяемой переменной, вам нужно добавить global var в эту функцию

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

добавление: global myString1 выше: myString1 = newString

должно решить проблему.

для дальнейшего чтения см. python do c

...