Превышена максимальная глубина рекурсии в классе

Я пишу матричный класс и хочу поместить метод того же класса в класс атрибутов

class Matrix:
    def __init__(
            self, 
            rows: int=None, 
            columns: int=None, 
            values: list[int | float | list[int | float]]=None
        ) -> None:
        self.__rows = 3 if not rows else (3 if rows <= 0 else rows)
        self.__columns = 3 if not columns else (3 if columns <= 0 else columns)
        self.__values = [
                            [
                                random.randint(-10, 10) 
                                for _ in range(self.__columns)
                            ]
                            for _ in range(self.__rows)
                        ] if not values and self.__rows != 1 \
                        else [
                            random.randint(-10, 10)
                            for _ in range(self.get_columns)
                        ] if self.__rows == 1 else values
        
        self.T = self.__transposition()
    
   
    
    def __transposition(self) -> typing.Self:
        return Matrix(
            self.__columns, 
            self.__rows, 
            [
                [
                    self.__values[j][i] 
                    for j in range(self.__rows)
                ] 
                for i in range(self.__columns)
            ]
        )
    
    
if name == 'main': 
    a = Matrix(rows=2)  
    print(a.T)

Но есть глубина рекурсии

File "Matrix.py", line 25, in __init__
    self.T = self.__transposition()
             ^^^^^^^^^^^^^^^^^^^^^^
  File "Matrix.py", line 47, in __transposition
    return Matrix(
           ^^^^^^^
RecursionError: maximum recursion depth exceeded

Что можно сделать? Я пытался пропустить его через декоратора статического метода, но ничего не помогло.


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

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

Ну вы же в __init__ сразу вызываете транспонирование, а в транспонировании создаете новый объект, вот и получается бесконечная рекурсия.

Нужно не вызывать транспонирование при инициализации, а делать его при обращении к атрибуту T, для этого он должен быть методом с декоратором @property:

class Matrix:
    def __init__(
            self, 
            rows: int=None, 
            columns: int=None, 
            values: list[int | float | list[int | float]]=None
        ) -> None:
        ...
        # Эту строку убираете:
        # self.T = self.__transposition()
    
    def __transposition(self) -> typing.Self:
        ...

    @property
    def T(self):
        return self.__transposition()
    
    
if name == 'main': 
    a = Matrix(rows=2)  
    print(a.T)

Вместо объявления T как метода можно записать так:

class Matrix:
    def __init__(
            self, 
            rows: int=None, 
            columns: int=None, 
            values: list[int | float | list[int | float]]=None
        ) -> None:
        ...
        # Эту строку убираете:
        # self.T = self.__transposition()

    def __transposition(self) -> typing.Self:
        ...

    T = property(__transposition)

Суть будет примерно та же, что и выше, но без промежуточного метода, "просто" атрибут T становится свойством для метода __transposition.

→ Ссылка