Как мне получить имя функции или метода из функции или метода Python?

Я чувствую, что должен это знать, но я не мог этого понять ...

Я хочу получить имя метода - который является интеграционным тестом - изнутри, чтобы он мог распечатать некоторый диагностический текст. Я могу, конечно, просто жестко закодировать имя метода в строке, но я бы хотел, чтобы тест был более СУХИМ, если это возможно.

возможный дубликат Как получить имя функции в виде строки в Python?

DarenW 28.12.2012 22:56

@DarenW Это не так. Запрос имени функции из переменной, содержащей объект функции, и запрос имени функции изнутри - это два очень разных вопроса.

Pavel Šimerda 12.02.2016 18:27
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
42
2
10 858
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Я думаю, что у модуля traceback может быть то, что вы ищете. В частности, функция extract_stack, похоже, справится со своей задачей.

Этот декоратор делает имя метода доступным внутри функции, передавая его в качестве аргумента ключевого слова.

from functools import wraps
def pass_func_name(func):
    "Name of decorated function will be passed as keyword arg _func_name"
    @wraps(func)
    def _pass_name(*args, **kwds):
        kwds['_func_name'] = func.func_name
        return func(*args, **kwds)
    return _pass_name

Вы бы использовали это так:

@pass_func_name
def sum(a, b, _func_name):
    print "running function %s" % _func_name
    return a + b

print sum(2, 4)

Но, возможно, вы захотите написать то, что хотите, прямо внутри самого декоратора. Тогда код является примером способа получить имя функции в декораторе. Если вы дадите более подробную информацию о том, что вы хотите сделать в функции, для которой требуется имя, возможно, я могу предложить что-то еще.

+1 при использовании декоратора вместо того, чтобы полагаться на детали реализации

Matthew Trevor 29.10.2008 07:07

@MatthewTrevor Если честно, я вижу, что декоратор полагается на детали реализации. Согласно stackoverflow.com/questions/251464/…, лучше использовать .__name__ вместо .func_name. Однако я согласен с основной идеей.

Pavel Šimerda 12.02.2016 18:29

Кажется, это самый простой способ использования модуля inspect:

import inspect
def somefunc(a,b,c):
    print "My name is: %s" % inspect.stack()[0][3]

Вы можете обобщить это следующим образом:

def funcname():
    return inspect.stack()[1][3]

def somefunc(a,b,c):
    print "My name is: %s" % funcname()

Кредит Стефан Липпенс, который был найден через Google.

# file "foo.py" 
import sys
import os

def LINE( back = 0 ):
    return sys._getframe( back + 1 ).f_lineno
def FILE( back = 0 ):
    return sys._getframe( back + 1 ).f_code.co_filename
def FUNC( back = 0):
    return sys._getframe( back + 1 ).f_code.co_name
def WHERE( back = 0 ):
    frame = sys._getframe( back + 1 )
    return "%s/%s %s()" % ( os.path.basename( frame.f_code.co_filename ),     
                            frame.f_lineno, frame.f_code.co_name )

def testit():
   print "Here in %s, file %s, line %s" % ( FUNC(), FILE(), LINE() )
   print "WHERE says '%s'" % WHERE()

testit()

Выход:

$ python foo.py
Here in testit, file foo.py, line 17
WHERE says 'foo.py/18 testit()'

Используйте "back = 1", чтобы найти информацию о двух уровнях вниз по стеку и т. д.

Ответ принят как подходящий

Ответы, связанные с самоанализом через inspect и тому подобное, разумны. Но может быть и другой вариант, в зависимости от вашей ситуации:

Если ваш интеграционный тест написан с помощью модуля модульный тест, вы можете использовать self.id() в своем TestCase.

Я только что обнаружил, что self.id () работает в методе unittest setUp () (он возвращает имя теста, а не сам setUp), в отличие от других решений. Поэтому я заменяю это на принятый ответ на этот конкретный вопрос.

Daryl Spitzer 30.10.2008 00:51

Другие вопросы по теме