"""
    https://stepik.org/lesson/701990/step/10?unit=702091

В программе необходимо объявить классы для работы с кошельками в разных валютах:
MoneyR - для рублевых кошельков
MoneyD - для долларовых кошельков
MoneyE - для евро-кошельков

Объекты этих классов могут создаваться командами:
rub = MoneyR()   # с нулевым балансом
dl = MoneyD(1501.25) # с балансом в 1501.25 долларов
euro = MoneyE(100)  # с балансом в 100 евро
>>> rub = MoneyR()
>>> dl = MoneyD(1501.25)
>>> euro = MoneyE(100)
>>> rub.volume, dl.volume, euro.volume
(0, 1501.25, 100)

В каждом объекте этих классов должны формироваться локальные атрибуты:
__cb - ссылка на класс CentralBank (центральный банк, изначально None);
__volume - объем денежных средств в кошельке (если не указано, то 0).

Также в классах MoneyR, MoneyD и MoneyE должны быть объекты-свойства (property) для работы с локальными атрибутами:
cb - для изменения и считывания данных из переменной __cb;
volume - для изменения и считывания данных из переменной __volume.

Объекты классов должны поддерживать следующие операторы сравнения:
rub < dl
dl >= euro
rub == euro  # значения сравниваются по текущему курсу центрального банка с погрешностью 0.1 (плюс-минус)
euro > rub
При реализации операторов сравнения считываются соответствующие значения __volume из сравниваемых объектов и приводятся к рублевому эквиваленту в соответствии с курсом валют центрального банка.

Чтобы каждый объект классов MoneyR, MoneyD и MoneyE "знал" текущие котировки, необходимо в программе объявить еще один класс CentralBank. 
Объекты класса CentralBank создаваться не должны (запретить), при выполнении команды:
>>> CentralBank()

должно просто возвращаться значение None. А в самом классе должен присутствовать атрибут:

rates = {'rub': 72.5, 'dollar': 1.0, 'euro': 1.15}
>>> CentralBank.rates
{'rub': 72.5, 'dollar': 1.0, 'euro': 1.15}

Здесь числа (в значениях словаря) - курс валюты по отношению к доллару. 

Также в CentralBank должен быть метод уровня класса:
register(cls, money) - для регистрации объектов классов MoneyR, MoneyD и MoneyE.

При регистрации значение __cb объекта money должно ссылаться на класс CentralBank. 
Через эту переменную объект имеет возможность обращаться к атрибуту rates класса CentralBank и брать нужные котировки.

Если кошелек не зарегистрирован, то при операциях сравнения должно генерироваться исключение:
raise ValueError("Неизвестен курс валют.")
Пример использования классов (эти строчки в программе писать не нужно):

>>> CentralBank.rates = {'rub': 72.5, 'dollar': 1.0, 'euro': 1.15}
>>> r = MoneyR(45000)
>>> d = MoneyD(500)
>>> CentralBank.register(r)
>>> CentralBank.register(d)
>>> r > d, r.value, d.value
(True, 620.6896551724138, 500.0)

if r > d:
    print("неплохо")
else:
    print("нужно поднажать")

>>> r2 = MoneyR(100)
>>> r2 > r
Traceback (most recent call last):
    ...
ValueError: Неизвестен курс валют.
    
P.S. В программе на экран ничего выводить не нужно, только объявить классы.
"""

from functools import total_ordering


class CentralBank:
    rates = {"rub": 72.5, "dollar": 1.0, "euro": 1.15}

    def __new__(self):
        ...

    @classmethod
    def register(cls, obj):
        obj.register_cb(cls)


@total_ordering
class Wallet:
    currency: str

    def __repr__(self):
        return f"{self.__class__.__name__}({self.volume!r})"

    def register_cb(self, cb: type):
        self.cb = cb

    def __init__(self, volume=0):
        self.cb = None
        self.volume = volume

    def __eq__(self, other):
        if hasattr(other, "value"):
            return abs(self.value - other.value) <= 0.1
        return NotImplemented

    def __lt__(self, other):
        if hasattr(other, "value"):
            return abs(self.value - other.value) > 0.1 and self.value < other.value
        return NotImplemented

    @property
    def cb(self):
        return getattr(self, f"_{self.__class__.__name__}__cb")

    @cb.setter
    def cb(self, value):
        setattr(self, f"_{self.__class__.__name__}__cb", value)

    @property
    def volume(self):
        return getattr(self, f"_{self.__class__.__name__}__volume")

    @volume.setter
    def volume(self, value):
        setattr(self, f"_{self.__class__.__name__}__volume", value)

    @property
    def rate(self):
        if not self.cb:
            raise ValueError("Неизвестен курс валют.")
        return self.cb.rates[self.currency]

    @property
    def value(self):
        return self.volume / self.rate


class MoneyR(Wallet):
    currency = "rub"


class MoneyD(Wallet):
    currency = "dollar"


class MoneyE(Wallet):
    currency = "euro"


if __name__ == "__main__":
    import doctest

    doctest.testmod()