В представленном коде `func2` превращается в замыкание, возвращаемое функцией `func`. Поэтому когда вы печатаете `func2`, вы печатаете объект функции, который возвращается функцией `func`.
Если используется `s = func(func2)`, то это просто другой способ записи, где результат вызова `func(func2)` присваивается переменной `s` вместо того, чтобы перезаписывать `func2`. В обоих случаях переменная `s` или `func2` будет ссылаться на функцию `func1`, которая определена внутри `func`.
Но есть важное различие в том, как вы потом можете использовать `func2` и `s`. Если вы вызовете `func2()`, будет выполнена внутренняя функция `func1`. Если вы попытаетесь вызвать `s`, то во втором варианте кода, где используется `s`, вы получите ошибку, если перед этим не выполните `s = s()`, потому что `s` изначально будет объектом функции, а не результатом её выполнения.
s = func(func2)
print(s)
В этом коде переменной `s` присваивается функция `func(func2)`. При вызове `s()` будет выводиться приветствие, результат выполнения функции `func2()` (который в данном случае равен строке 'Андрей' и прощание.
В ответ на ваш вопрос, отличие этого кода от кода, где вместо последних двух строк написано `s = func(func2)`, заключается в том, что в первом случае результат вызова `func(func2)` присваивается переменной `s`, а затем `s` вызывается как функция `s()`. Во втором случае результат вызова `func(func2)` присваивается переменной `s`, и `s` может быть вызвана как функция `s()`.