Я создаю программу для расчета стоимости телекоммуникационного пакета на основе истории звонков. Вот основная функция.
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
Скажите, пожалуйста, есть ли способ изменить эти глобальные переменные на локальные.
У вас есть global cheap_minutes_used
, но вы никогда не используете эту переменную.
Поместите состояние, которое должно сохраняться между вызовами, в словарь. Передайте это как аргумент 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()?
Я подумал о том, чтобы написать это в ответе, но решил, что это больше работы, чем я хотел вложить в это.
Но вам должно быть довольно легко сделать это с классом данных.
@Barmar Он по-прежнему глобальный. Вы передаете глобальный словарь в качестве параметра, который в конечном итоге устанавливает его как локальную, но также и как глобальную переменную. Он не был изменен, он стал и тем, и другим.
@EdenRefaelov Но вы можете использовать разные словари в разных циклах, поэтому можно избежать проблемы с использованием определенной глобальной переменной в функции.
@Barmar Решение, которое вы предложили, использует тот же словарь (тот же адрес/объект) по ссылке. Когда вы измените state: dict
, state_dict
тоже изменится.
@EdenRefaelov Конечно. Насколько я понимаю, они хотят перенести эти текущие итоги из одной строки в другую в цикле apply()
. Поэтому им нужно что-то, что сохраняется между вызовами. Инкапсулировать его в изменяемый объект лучше, чем жестко запрограммировать глобальные переменные.
ваш вызов функции находится в строке с комментариями. Как вы на самом деле вызываете функцию?