Как разобраться с классами в Питоне?
random.shuffle определён в модуле random и не принадлежит к числу методов класса list, каковые перечислены здесь. Так сложилось исторически.

Итак, self обычно возникает, когда ты сам создаёшь класс и его методы. При использовании класса self не нужен, баста.

С другой стороны, смотри: вот метод list.reverse()
l = [1, 2, 3]
l.reverse() # [3, 2 ,1]это очень похоже на то, что делал random.shuffle, но сейчас сделаем совсем неотличимо:
l = [1, 2, 3]
list.reverse(l) # [3, 2 ,1]
да, где-то там в потрохах стандартной библиотеки описан класс list, у которого есть метод reverse(), но нет метода shuffle(). Поэтому ты можешь обратиться  к первому в синтаксисе l.reverse(), а ко второму не можешь. Но в другом синтаксисе, class.method(instance) ты можешь обратиться и к одному, и ко второму! Это, кстати, благодаря тому, что модуль тоже класс, как и многое в питоне, а описанные в модуле функции - атрибуты модуля.
random.shuffle определён в модуле random и не принадлежит к числу методов класса list, каковые перечислены здесь. Так сложилось исторически.

Итак, self обычно возникает, когда ты сам создаёшь класс и его методы. При использовании класса self не нужен, баста.

С другой стороны, смотри: вот метод list.reverse()
l = [1, 2, 3]
l.reverse() # [3, 2 ,1]это очень похоже на то, что делал random.shuffle, но сейчас сделаем совсем неотличимо:
l = [1, 2, 3]
list.reverse(l) # [3, 2 ,1]
да, где-то там в потрохах стандартной библиотеки описан класс list, у которого есть метод reverse(), но нет метода shuffle(). Поэтому ты можешь обратиться  к первому в синтаксисе l.reverse(), а ко второму не можешь. Но в другом синтаксисе, class.method(instance) ты можешь обратиться и к одному, и ко второму! Это, кстати, благодаря тому, что модуль тоже класс, как и многое в питоне, а описанные в модуле функции - атрибуты модуля.