#python #data-structures
#python #структуры данных
Вопрос:
У меня есть Category
класс, и для каждого экземпляра этого класса есть атрибут ledger. Этот атрибут книги фактически представляет собой список словарей, которые содержат суммы вывода и депозита и описания в форме {"amount" : amount, "description" : description}
. Теперь я хочу определить функцию create_spend_chart
, которая будет принимать список объектов в качестве параметра и найдет общую сумму вывода. Я смог сделать это успешно:
def create_spend_chart(categories):
total_withdrawn = 0
for i in categories:
for p in i.ledger:
if p["amount"] < 0:
total_withdrawn = -p["amount"]
Но проблема, с которой я сталкиваюсь здесь, заключается в том, что я не могу сохранить общую сумму вывода для каждого объекта категории отдельно. Как я могу это сделать?
Моя кодовая база может помочь вам ответить на вопрос:
class Category:
def __init__(self, name):
self.name = name
self.ledger = list()
def get_balance(self):
total_balance = 0
for i in self.ledger:
total_balance = i["amount"]
return total_balance
def check_funds(self, amount):
if self.get_balance() >= amount:
return True
else:
return False
def deposit(self, amount, description = "Deposit"):
form = {"amount" : int(amount), "description" : description}
self.ledger.append(form)
def withdraw(self, amount, description = "Withdrawal"):
if description == None:
description = "Withdrawal"
form = {"amount" : -int(amount), "description" : description}
if self.check_funds(amount):
self.ledger.append(form)
return True
else:
return False
def transfer(self, amount, category_object):
form1 = {"amount" : -int(amount), "description" : f"Transfer to {category_object.name}"}
form2 = {"amount" : int(amount), "description" : f"Transfer from {self.name}"}
if self.check_funds(amount):
self.ledger.append(form1)
category_object.ledger.append(form2)
return True
else:
return False
def __repr__(self):
Ledger = ""
for i in self.ledger:
if len(i["description"]) > 23:
des = i["description"][:23]
else:
des = i["description"]
Ledger = des.ljust(23) str(round(i["amount"], 2)).rjust(7) "n"
Ledger = Ledger "Total: " str(round(self.get_balance(), 2))
receipt = f"{self.name}".center(30, "*") "n" Ledger
return receipt
def create_spend_chart(categories):
total_withdrawn = 0
withdrawals = list()
for i in categories:
for p in i.ledger:
if p["amount"] < 0:
total_withdrawn = -p["amount"]
PS: Эта функция не является методом, она определяется вне объявления класса.
Ответ №1:
Используйте a collections.defaultdict
, чтобы сделать такие агрегации простыми, как пирог.
import collections
# ...
withdrawn_per_category = collections.defaultdict(int)
for i in categories:
for p in i.ledger:
if p["amount"] < 0:
withdrawn_per_category[i.name] = -p["amount"]
(Я решил использовать int
в качестве типа данных по умолчанию, но здесь это не имеет большого значения, если это конвертируемый числовой тип.)
Без collections
Если по какой-то причине вы не хотите использовать удобный встроенный collections
модуль, вы можете самостоятельно эмулировать то же поведение с помощью обычного dict:
withdrawn_per_category = {}
for i in categories:
for p in i.ledger:
if p["amount"] < 0:
withdrawn_per_category[i.name] = withdrawn_per_category.get(i.name, 0) - p["amount"]
Комментарии:
1. Спасибо за ответ!! Есть ли какой-либо способ, которым я мог бы сохранить эти значения (снятие средств для каждой категории) в списке вместо словаря?
2. Конечно. Самым простым способом было бы сделать что-то вроде
withdrawals_per_category_list = list(withdrawn_per_category.items())
после того, как вы это сделали.3. К сожалению, я столкнулся с проблемой. Когда я сейчас запускаю программу, она выдает ошибку
NameError: name 'collections' is not defined
. Что мне с этим делать?4. Добавить
import collections
.5. Да, есть, но зачем беспокоиться?
collections
это встроенный модуль, он доступен с каждым Python. (Тем не менее, я добавил версию dict без коллекций.)