vendredi 7 avril 2023

Multiple calling @property that reduce list

I'm training my skills of design patterns. With a Factory schema i tried to get and pop example numbers from a imited list.

With initialization of seccond account i recieved an IndexError. In debug mote i noticed that between initialisation of acc01 and acc02 I have a 4 uses of AccountManager.number() func. Same with AccountManager.account_id().

from abc import ABC
from random import choice, randint


class AccountsManager:
    def __init__(self) -> None:
        self._last_id_number = 0
        self._allowed_numbers = [randint(10_000, 99_999) for _ in range(5)]

    @property
    def number(self) -> int:
        if not self._allowed_numbers:
            raise IndexError
        number = choice(self._allowed_numbers)
        self._allowed_numbers.pop(self._allowed_numbers.index(number))
        return number

    @property
    def account_id(self) -> int:
        account_id = self._last_id_number
        self._last_id_number += 1
        return account_id


class TemplateBankAccount(ABC):
    def __init__(self, manager, owner: str, account_type: str = '') -> None:
        self.manager = manager
        self.id_number = manager.account_id
        self.account_number = manager.number

        self.owner = owner
        self.account_type = account_type
        self._amount = 0

    def __str__(self) -> None:
        raise NotImplementedError

    @property
    def amount(self) -> int:
        return self._amount

    @amount.setter
    def amount(self, direction: str, value: int) -> None:
        if direction == '+':
            self._amount += value
        elif direction == '-':
            self._amount -= value
        else:
            raise ValueError


class PersonalBankAccount(TemplateBankAccount):
    def __init__(self, manager, owner) -> None:
        super().__init__(manager, owner, account_type='Personal Account')

    def __str__(self) -> str:
        return f'{self.account_type}: {self.owner}'


class CompanyBankAccount(TemplateBankAccount):
    def __init__(self, manager, owner) -> None:
        super().__init__(manager, owner, account_type='Company Account')

    def __str__(self) -> str:
        return f'{self.account_type}: owner name restricted.'


class SavingsBankAccount(TemplateBankAccount):
    def __init__(self, manager, owner) -> None:
        super().__init__(manager, owner, account_type='Savings Account')

    def __str__(self) -> str:
        return f'{self.account_type}: {self.owner}'


class AccountCreator:
    def __init__(self) -> None:
        self.manager_group = AccountsManager()

    def create_account(self, owner_name, account_type):
        allowed_types = {'Personal': PersonalBankAccount(self.manager_group, owner_name),
                         'Company': CompanyBankAccount(self.manager_group, owner_name),
                         'Savings': SavingsBankAccount(self.manager_group, owner_name)}

        return allowed_types.get(account_type, 'Non offered account type')


def main() -> None:
    creator = AccountCreator()
    create_account = creator.create_account
    acc_01 = create_account('Andrew Wiggins', 'Personal')
    acc_02 = create_account('NASA Inc.', 'Company')
    acc_03 = create_account('John Paul Wieczorek', 'Savings')

    list_of_accounts = [str(account) for account in (acc_01, acc_02, acc_03)]
    print('\n'.join(list_of_accounts))


if __name__ == '__main__':
    main()

I do not know how to change code to get values from self._last_id_number and self._allowed_numbers only once per create_account call.

Aucun commentaire:

Enregistrer un commentaire