Сделать глобальные переменные локальными переменными

Я создаю программу для расчета стоимости телекоммуникационного пакета на основе истории звонков. Вот основная функция.

from math import ceil

prev_date = None
expen_minutes_used = 0

def calculate_call_cost(row):
    
    global prev_date, expen_minutes_used 

    if prev_date is None or row['data of call'].date() != prev_date:
        prev_date = row['data of call'].date() 
        expen_minutes_used = 0

    expen_minutes = 0
    if expen_minutes_used < 5:
        expen_minutes = min(5 - expen_minutes_used, ceil(row['Duration in second'] / 60))
                        
        expen_minutes_used += expen_minutes 

    cheap_minutes = ceil(row['Duration in second'] / 60) - expen_minutes
                    
    
    cost = cheap_minutes * 0.40 + expen_minutes * 3.95
    return cost

calls_data_sorted['Cost of tariff'] = calls_data_sorted.apply(calculate_call_cost, axis = 1) 
total_cost2 = calls_data_sorted['Cost of tariff'].sum()
calls_data_sorted

Скажите, пожалуйста, есть ли способ изменить эти глобальные переменные на локальные.

ваш вызов функции находится в строке с комментариями. Как вы на самом деле вызываете функцию?

Barmar 05.04.2024 00:05

У вас есть global cheap_minutes_used, но вы никогда не используете эту переменную.

Barmar 05.04.2024 00:09
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поместите состояние, которое должно сохраняться между вызовами, в словарь. Передайте это как аргумент calculate_call_cost(), и функция сможет обновить словарь.

from math import ceil

state_dict = {'prev_date': None, 'expen_minutes_used': 0}

def calculate_call_cost(row, state: dict):
    if state['prev_date'] is None or row['data of call'].date() != state['prev_date']:
        state['prev_date'] = row['data of call'].date() 
        state['expen_minutes_used'] = 0

    expen_minutes = 0
    if state['expen_minutes_used'] < 5:
        expen_minutes = min(5 - state['expen_minutes_used'], ceil(row['Duration in second'] / 60))
                        
        state['expen_minutes_used'] += expen_minutes 

    cheap_minutes = ceil(row['Duration in second'] / 60) - expen_minutes
                    
    
    cost = cheap_minutes * 0.40 + expen_minutes * 3.95
    return cost

calls_data_sorted['Cost of tariff'] = calls_data_sorted.apply(lambda row: calculate_call_cost(row, state_dict), axis = 1) 
total_cost2 = calls_data_sorted['Cost of tariff'].sum()

Вы также можете создать класс с calculate_call_cost() в качестве метода. Переменные, которые необходимо сохранить, могут быть атрибутами класса.

не могли бы вы подробно рассказать о создании класса с использованием метода Calcul_call_cost()?

lelelel 05.04.2024 00:25

Я подумал о том, чтобы написать это в ответе, но решил, что это больше работы, чем я хотел вложить в это.

Barmar 05.04.2024 00:26

Но вам должно быть довольно легко сделать это с классом данных.

Barmar 05.04.2024 00:26

@Barmar Он по-прежнему глобальный. Вы передаете глобальный словарь в качестве параметра, который в конечном итоге устанавливает его как локальную, но также и как глобальную переменную. Он не был изменен, он стал и тем, и другим.

Eden Refaelov 05.04.2024 01:33

@EdenRefaelov Но вы можете использовать разные словари в разных циклах, поэтому можно избежать проблемы с использованием определенной глобальной переменной в функции.

Barmar 05.04.2024 01:34

@Barmar Решение, которое вы предложили, использует тот же словарь (тот же адрес/объект) по ссылке. Когда вы измените state: dict, state_dict тоже изменится.

Eden Refaelov 05.04.2024 01:37

@EdenRefaelov Конечно. Насколько я понимаю, они хотят перенести эти текущие итоги из одной строки в другую в цикле apply(). Поэтому им нужно что-то, что сохраняется между вызовами. Инкапсулировать его в изменяемый объект лучше, чем жестко запрограммировать глобальные переменные.

Barmar 05.04.2024 01:39

Другие вопросы по теме