2008-10-30 1 views
422

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

def my_function(): 
    pass 

print get_function_name_as_string(my_function) # my_function is not in quotes 

должно выводить "my_function".

Возможно ли это в python? Если нет, любая идея, как написать get_function_name_as_string в Python?

+0

http: // stackoverflow.com/questions/245304/how-do-i-get-the-name-of-a-function-or-method-from-in-a-python-function - или – 2008-11-01 15:31:16

+1

В следующий раз укажите свою мотивацию в вопросе. В его нынешнем виде это, по-видимому, смущает людей, и некоторые из них склонны предполагать, что вы будете называть дословно `get_function_name_as_string (my_function)` и ожидаете `` my_function "` как результат. Я предполагаю, что ваша мотивация - это общий код, который работает с функцией как объект первого класса и должен получить имя функции, переданной в качестве аргумента. – 2016-02-12 15:24:48

+8

Мотивация, стоящая за вопросом, НЕ СООТВЕТСТВУЕТ техническому ответу. Прекратите использовать его в качестве предлога, чтобы издеваться, критиковать, интеллектуально осанки и избегать ответов. – CogitoErgoCogitoSum 2017-08-27 19:04:24

ответ

531
my_function.__name__ 

Использование __name__ является предпочтительным методом, как оно применяется равномерно. В отличие от func_name, он работает на встроенных функций, а также:

>>> import time 
>>> time.time.func_name 
Traceback (most recent call last): 
    File "<stdin>", line 1, in ? 
AttributeError: 'builtin_function_or_method' object has no attribute 'func_name' 
>>> time.time.__name__ 
'time' 

Также двойные подчеркивания указывают читателю это специальный атрибут. В качестве бонуса классы и модули также имеют атрибут __name__, поэтому вы помните только одно специальное имя.

35
my_function.func_name 

Есть и другие забавные свойства функций. Введите dir(func_name), чтобы перечислить их. func_name.func_code.co_code - это скомпилированная функция, хранящаяся в виде строки.

import dis 
dis.dis(my_function) 

покажет код в почти читаемом формате. :)

+2

В чем разница между f .__ name__ и f.func_name? – 2008-10-30 19:43:02

+0

Они такие же. http://www.python.org/doc/2.5.2/ref/types.html#types – 2008-10-30 19:48:22

+0

двойные имена подчеркивания традиционно считаются частными, хотя никогда не применялись. Поэтому лучше использовать func_name, даже если они могут быть одинаковыми. – 2008-10-30 20:11:50

175

Вы также можете использовать

import sys 
this_function_name = sys._getframe().f_code.co_name 
10

sys._getframe() не гарантируется быть доступны во всех реализациях Python (see ref), вы можете использовать модуль, чтобы сделать обратное прослеживание то же самое, например.

import traceback 
def who_am_i(): 
    stack = traceback.extract_stack() 
    filename, codeline, funcName, text = stack[-2] 

    return funcName 

Вызов стека [-1] будет возвращать текущие детали процесса.

27

Эта функция вернет имя функции вызывающего абонента.

def func_name(): 
    import traceback 
    return traceback.extract_stack(None, 2)[0][2] 

Это похоже на ответ Альберта Вонпуппа с дружеской упаковкой.

6

В качестве расширения @Demyn's answer, я создал некоторые вспомогательные функции, которые печатают имя текущей функции и аргументы в текущей функции по:

import inspect 
import logging 
import traceback 

def get_function_name(): 
    return traceback.extract_stack(None, 2)[0][2] 

def get_function_parameters_and_values(): 
    frame = inspect.currentframe().f_back 
    args, _, _, values = inspect.getargvalues(frame) 
    return ([(i, values[i]) for i in args]) 

def my_func(a, b, c=None): 
    logging.info('Running ' + get_function_name() + '(' + str(get_function_parameters_and_values()) +')') 
    pass 

logger = logging.getLogger() 
handler = logging.StreamHandler() 
formatter = logging.Formatter(
    '%(asctime)s [%(levelname)s] -> %(message)s') 
handler.setFormatter(formatter) 
logger.addHandler(handler) 
logger.setLevel(logging.INFO) 

my_func(1, 3) # 2016-03-25 17:16:06,927 [INFO] -> Running my_func([('a', 1), ('b', 3), ('c', None)]) 
7

Мне нравится использовать функцию декоратора. Я добавил класс, который также умножает время функции. Предположим, GLog стандартный питон регистратор:

class EnterExitLog(): 
    def __init__(self, funcName): 
     self.funcName = funcName 

    def __enter__(self): 
     gLog.debug('Started: %s' % self.funcName) 
     self.init_time = datetime.datetime.now() 
     return self 

    def __exit__(self, type, value, tb): 
     gLog.debug('Finished: %s in: %s seconds' % (self.funcName, datetime.datetime.now() - self.init_time)) 

def func_timer_decorator(func): 
    def func_wrapper(*args, **kwargs): 
     with EnterExitLog(func.__name__): 
      return func(*args, **kwargs) 

    return func_wrapper 

так что теперь все, что вам нужно сделать с вашей функцией является украсить его и вуаля

@func_timer_decorator 
def my_func(): 
6

Если вы заинтересованы в методах класса тоже, Python 3.3+ имеет __qualname__ в дополнение к __name__.

def my_function(): 
    pass 

class MyClass(object): 
    def method(self): 
     pass 

print(my_function.__name__)   # gives "my_function" 
print(MyClass.method.__name__)  # gives "method" 

print(my_function.__qualname__)  # gives "my_function" 
print(MyClass.method.__qualname__) # gives "MyClass.method" 
Смежные вопросы