Как избежать глобальных переменных в Python - PullRequest
0 голосов
/ 08 ноября 2019

Я знаю, что есть много сообщений на эту тему, но у меня возникли проблемы с пониманием концепции. Поэтому я написал сценарий, и технический директор моей компании отругал меня за это, сказав, что это плохой стиль, поскольку он использует экземпляр объекта, который является глобальным переменным, который создается только в основной части сценария. Следовательно, функция не будет работать при импорте из другого места, где экземпляр не доступен глобально.

Редактировать: вот точная формулировка жалобы:

Функция def updateValues(...), например, использует экземпляр объекта, который является глобальной переменной и толькосоздано в основной части сценария. Эта функция не будет работать при импорте из другого места, где такой экземпляр недоступен в глобальной области видимости. Это плохой стиль программирования.

По моему мнению, я передаю экземпляр объекта функции в вызове, и поэтому он фактически не использует глобальную переменную. Ответы на вопросы остались без ответа, так как он уехал в отпуск. Тем не менее, это нужно развернуть, и я не уверен, что делать дальше, поэтому я обращаюсь к SO за помощью. Может быть, кто-то здесь знает, что он имел в виду :).

Это упрощение сценария:

# This is called when the object instance is created
def getInitialValues(projectID,initial_time):
    timeseries_1,timeseries_2 = getData(projectID,initial_time)
    value_1,value_2 = makeInitialCalculations(timeseries_1,timeseries_2)
    return value_1,value_2

# This is called once a minute to update the values with the new data
def updateValues(Object,time):
    # actually I only grab the "new" data since the last call of course, out of simplicity I didn't put that in here :)
    timeseries_1,timeseries_2 = getData(Object.projectID,time)
    Object.value_1,Object.value_2 = makeUpdateCalculations(Object.value_1,Object.value_2,timeseries_1,timeseries_2)


class Functions():
    def __init__(self,projectID,initial_time):
        self.projectID=projectID
        self.value_1,self.value_2 = getInitialValues(projectID,initial_time)


'''MAIN PART OF SCRIPT'''

# creating the object instance
obj_instance = Functions(projectID,datetime.now())

# the loop that is deployed on the server
while True:
    sleep(60)
    updateValues(obj_instance,datetime.now())
    putNewValuesInDatabase(obj_instance)

1 Ответ

1 голос
/ 08 ноября 2019

Программа может работать, но я думаю, что это не лучший стиль программирования, как предложили некоторые комментарии. Между прочим, я не вижу определения для putNewValuesInDatabase, поэтому я не знаю, просто ли вы его пропустили для краткости или он был бы в файле, который выполняет импорт этого файла. Независимо от того. Не путать проблему, но вот как я, вероятно, закодировал бы это (хотя я, вероятно, свернул бы getInitialValues в метод __init__ из-за его краткости):

class Functions():

    def __init__(self,
                 getData,
                 makeInitialCalculations,
                 makeUpdateCalculations,
                 putNewValuesInDatabase,
                 projectID):
        self.getData = getData
        self.makeInitialCalculations = makeInitialCalculations
        self.makeUpdateCalculations = makeUpdateCalculations
        self.putNewValuesInDatabase = putNewValuesInDatabase 
        self.projectID = projectID
        self.getInitialValues()
        self.start_updates()

    def getInitialValues(self):
        time = datetime.now()
        timeseries_1, timeseries_2 = self.getData(self.projectID, time)
        self.value_1, self.value_2 = self.makeInitialCalculations(timeseries_1, timeseries_2, time)

    def updateValues(self):
        time = datetime.now()
        timeseries_1, timeseries_2 = self.getData(self.projectID, time)
        self.value_1, self.value_2 = self.makeUpdateCalculations(self.value_1, self.value_2, timeseries_1,timeseries_2)

    def start_updates(self):
        while True:
            sleep(60)
            self.updateValues()
            self.putNewValuesInDatabase(self)            

Я включилgetInitialValues и updateValues в ваш (не очень хорошо названный) класс Functions и упростили интерфейсы. Обратите внимание, что теперь конструктору для этого класса должны быть переданы функции getData, makeInitialCalculations, makeUpdatecalculations и putNewValuesInDatabase, которые могут исходить из кода клиента, который может находиться в другом файле. это импортирует этот файл. Тогда я бы ожидал, что клиентский код будет:

obj_instance = Functions(getData, makeInitialCalculations, makeUpdateCalculations, putNewValuesInDatabase, projectID)

Вместо этого вы можете захотеть, чтобы конструктор автоматически не вызывал start_updates (или getInitialValues в этом отношении) и чтобы клиентский код вызывал эти методы(ы) вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...