Как получить атрибут экземпляра обработав его?

Как получить атрибут экземпляра обработав его?

Пример:


@dataclass
class Food:
    # Белка в 100гр рыбы, в гр
    p_100g: float


fish = Food(123)

# Содержимое белка в 100гр рыбы в кг
fish_protein_100g_in_kg = fish.p_100g / 1000

# Как получить то же самое при помощи синтаксиса fish.kg.p_100g?

Пытался сделать при помощи __getattr__() и __getattribute__()- что-то не могу понять как


Ответы (3 шт):

Автор решения: Alpensin

Данный код не имеет практической ценности. Не надо так делать. Если это какая-то практическая задача, подумайте над более грамотным подходом. Например можно добавить классу Food метод для конвертации в указанную размерность отдаваемых значений.

А так вот как вы просили

@dataclass
class Food:
    # Белка в 100гр рыбы, в гр
    p_100g: float

    def __getattr__(self, name):
        cls = type(self) 
        if name == 'kg':
            return Food(self.p_100g / 1000)
        msg = f'{cls.__name__!r} object has no attribute {name!r}'
        raise AttributeError(msg)

fish = Food(123)
fish.kg.p_100g
# 0.123
→ Ссылка
Автор решения: Alpensin

Можно применить такой вариант решения

class Weight:
    DIMENSIONS = {
            'g': 1,
            'kg': 1000
            }
    def __init__(self, value, dim):
        try:
            dim_coef = self.DIMENSIONS[dim]
        except KeyError as exc:
            raise KeyError(f"Unknown dimension {dim}") from exc
        self.value_in_g = value * dim_coef

    @property
    def g(self):
        return self.value_in_g

    @property
    def kg(self):
        return round(self.value_in_g / self.DIMENSIONS['kg'], 2)

    
@dataclass
class Food:
    # Белка в 100гр рыбы, в гр
    p_100g: Weight
 
fish = Food(Weight(123, 'g'))
fish.p_100g.kg
→ Ссылка
Автор решения: vadim vaduxa
from dataclasses import dataclass

@dataclass
class Food:
    p_100g: float

    def __post_init__(self):
        self.kg = KG(self)
        self.gg = GG(self)

@dataclass
class G:
    parent: Food

class KG(G):
    def __getattr__(self, item):
        return getattr(self.parent, item) / 1000

class GG(G):
    def __getattr__(self, item):
        return getattr(self.parent, item) + 1

if __name__ == '__main__':
    fish = Food(123)
    print(fish.kg.p_100g)  # 0.123
    print(fish.gg.p_100g)  # 124
→ Ссылка