class ListInherited:
    """
    Wykorzystujemy funkcję dir() do uzyskania listy atrybutów instancji
    oraz atrybutów odziedziczonych. To obejmuje domyślne nazwy dziedziczone z domyślnej klasy nadrzędnej 'object' powyżej                   
    najwyższych klas. Funkcja getattr() potrafi pobrać dziedziczone nazwy nieobecne w self.__dict__.

    Uwaga! Użyj __str__, zamiast __repr__, w przeciwnym razie kod może się zapętlić podczas wyświetlania metod z      
    wiązaniem, które mogą być zwracane dla niektórych atrybutów przez getattr(). 
    Zazwyczaj nie uda się to dla atrybutów slotów klasy, które nie zostały jeszcze przypisane.
    """

    def __attrnames(self, unders=False):
        result = '\n'
        for attr in dir(self):                                   # Funkcja dir instancji
            if attr[:2] == '__' and attr[-2:] == '__':           # Nazwy wewnętrzne
                result += f'\t{attr}\n' if unders else ''        # Pominięcie wewnętrznych nazw?
            else:
                result += f'\t{attr}={getattr(self, attr)!r}\n'
        return result

    def __str__(self):
        return (f'<Instancja of {self.__class__.__name__}, '      # Własna nazwa klasy
                f'adres {id(self):#x}:'                           # Własny adres (hex)
                f'{self.__attrnames()}>')                         # Lista nazwa= wartość

if __name__ == '__main__':
    import testmixin
    testmixin.tester(ListInherited)      # Test klasy z tego modułu

