Написать функцию whocall(depth=1), которая возвращает имя и названия параметров (строкой через пробел) одной из функций, вызов которой привёл к вызову whocall(). При depth=1 это функция, непосредственно вызвавшая whocall(), при depth=2 — функция, которая вызвала эту функцию и т. д. При depth=0 это сама whocall(). Если вызывающий объект не является функцией (например, это модуль) или depth превышает глубину стека вызовов, названия параметров — пустая строка; в последнем случае в качестве имени возвращается <UNIVERSE>.
В этом задании первый параметр метода — self — также надо указывать. Это упрощает решение, см. рассуждения в полной формулировке задачи
1 class C:
2 def fun(self, arg, *args, kw="KW", **kwargs):
3 return whocall(arg)
4 lfun = lambda self, arg: whocall(arg)
5
6 def fun():
7 return whocall(1)
8
9 print(C().fun(0), C().lfun(0), fun())
10 print(C().fun(1), C().lfun(1))
11 print(C().fun(2, 3, 4, kw=123), C().lfun(2))
12 print(C().fun(3), C().lfun(42))
Задача не простая: пример из лекции — вынуть объект по имени из .globals() — не зайдёт, потому что вызываемый объект не всегда доступен по имени (lambda, какая-нибудь, ссылки из списка функций и т. п.). Требуется исследование.
- Зато сам текст функции занимает семь строк
Я загуглил (см. спойлер) и пересоздал объект-функцию прямо из её кода с помощью types.FunctionType(), а уже от получившегося клона брал хорошую, годную сигнатуру.
По стеку вызовов нельзя понять, функция это или метод. Как следствие, self приехал в эту сигнатуру.
Спойлер: