Потому что в этой строке:
line_prefix = [''.join((str(value), " & ")) for value in penult_args]
вы извлекаете значения из исходного списка (за исключением последнего элемента), находясь в этой строке:
value = ''.join(('$', str(value), '$'))
Вы добавили $
, но никогда не сохраняли значение обратно в список.
5
получает $
только потому, что это последний элемент, поэтому вы ссылаетесь на него непосредственно в:
line_suffix = [''.join((str(value), " \\\\", "\n"))]
Лучший способ сделать все это:
def t_row(self, *args):
if len(args) == self.columns:
result = []
for value in args:
if isinstance(value, int):
result.append('$%d$' % value)
else:
result.append(value)
return ' $ '.join(result) + r' \\'
Как однострочник, это будет
t_row = lambda self, *args: (' $ '.join('$%d$' %
value if isinstance(value, int) else value for value in args) + r' \\'
if len(args) == self.columns else None)
но на самом деле это не очень хорошая идея.