स्ट्रिंग के रूप में एक फ़ंक्शन नाम कैसे प्राप्त करें?


740

पायथन में, मुझे फ़ंक्शन को कॉल किए बिना, स्ट्रिंग के रूप में एक फ़ंक्शन नाम कैसे मिलता है?

def my_function():
    pass

print get_function_name_as_string(my_function) # my_function is not in quotes

आउटपुट चाहिए "my_function"

क्या पायथन में ऐसा कार्य उपलब्ध है? यदि नहीं, तो get_function_name_as_stringपायथन में कैसे लागू करने के बारे में कोई विचार ?


जवाबों:


944
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__विशेषता भी होती है, इसलिए आपको केवल एक विशेष नाम याद होगा।


420
क्योंकि कुछ मामलों में, आपको अपने फ़ंक्शन के तर्क के रूप में कुछ फ़ंक्शन ऑब्जेक्ट मिलते हैं, और आपको उस फ़ंक्शन के नाम को प्रदर्शित / संग्रहीत / हेरफेर करने की आवश्यकता होती है। शायद आप प्रलेखन, सहायता पाठ, क्रियाओं का इतिहास आदि उत्पन्न कर रहे हैं, इसलिए नहीं, आप हमेशा फ़ंक्शन नाम को हार्डकोड नहीं कर रहे हैं।
मार्बेल जूल 26'13

2
@ मार्गरियल: मेरे कहने का मतलब यह है: मान लीजिए कि आपके पास एक ऐसा वर्ग है जो 100 विधियों को परिभाषित करता है, जहां सभी विधियाँ केवल आवरण होती हैं, जो एक निजी विधि कहलाती हैं, जो स्वयं आवरण का नाम है। कुछ इस तरह def wrapper(kwargs): super(ExtendedClass,self).call('wrapper', kwargs):। आप एक और विकल्प है, जो है: def wrapper(kwargs): super(ExtendedClass,self).call(sys._getframe().f_code.co_name, kwargs)। इसलिए, अल्बर्ट वोनपुप का जवाब मुझे बेहतर लगता है।
रिचर्ड गोम्स

19
@RichardGomes एक उत्तर फ़ंक्शन के भीतर नाम प्राप्त करने के लिए उपयुक्त है, दूसरा फ़ंक्शन संदर्भ से इसे प्राप्त करने के लिए उपयुक्त है। लिखित रूप में ओपी का प्रश्न उत्तरार्द्ध को दर्शाता है।
रसेल बोरोगोव

22
@RichardGomes वास्तव में मैं इस समस्या का हल खोजने के लिए इस सवाल पर आया था। मैं जिस समस्या का समाधान करने की कोशिश कर रहा हूं, वह एक डेकोरेटर है जिसका उपयोग मेरे सभी कॉल लॉग करने के लिए किया जा सकता है।
अली-हुसैन

23
@ रीचर्डगम्स फ़ंक्शंस प्रथम श्रेणी की वस्तुएं हैं, उनके लिए बाध्य नाम से अधिक हो सकते हैं। जरूरी नहीं कि ऐसा ही हो f.__name__ == 'f'
विम

298

इसके अंदर से वर्तमान फ़ंक्शन या विधि का नाम प्राप्त करने के लिए, विचार करें:

import inspect

this_function_name = inspect.currentframe().f_code.co_name

sys._getframeइसके बजाय काम करता है, inspect.currentframeहालांकि बाद वाला एक निजी फ़ंक्शन तक पहुंचने से बचता है।

बजाय बुला समारोह का नाम पाने के लिए, पर विचार f_backके रूप में inspect.currentframe().f_back.f_code.co_name


यदि उपयोग कर रहे हैं mypy, तो यह शिकायत कर सकता है कि:

त्रुटि: आइटम "वैकल्पिक" में से कोई नहीं [फ्रेम टाइप] "कोई विशेषता नहीं है" f_code "

उपरोक्त त्रुटि को दबाने के लिए, विचार करें:

import inspect
import types
from typing import cast

this_function_name = cast(types.FrameType, inspect.currentframe()).f_code.co_name

45
+1: यह वह उत्तर है जिसे मैं देखना चाहता हूं। अन्य उत्तर मानते हैं कि कॉलर पहले से ही फ़ंक्शन का नाम जानता है, जो इस प्रश्न के संदर्भ में बकवास है।
रिचर्ड गम्स

110
रिचर्ड: नहीं, यह नहीं है। आप मान रहे हैं कि आप सीधे अपने फ़ंक्शन पर नाम या func_name बुला रहे हैं , उसी दायरे में इसे परिभाषित किया गया था, जो अक्सर ऐसा नहीं होता है। ध्यान रखें कि फ़ंक्शंस ऑब्जेक्ट हैं - उन्हें अन्य फ़ंक्शंस के तर्कों के रूप में पास किया जा सकता है, बाद में देखने या निष्पादन के लिए सूचियों /
डिकेट्स

11
@paulus_almighty, स्टैक फ्रेम में खुदाई मुझे सार के रूप में हड़ताल नहीं करता है! वास्तव में, यह अमूर्त के विपरीत है। डॉक्स में कार्यान्वयन विवरण नोट देखें । पायथन के सभी कार्यान्वयन शामिल नहीं होंगे sys._getframe- यह सीधे सीपीथॉन के आंतरिक क्षेत्रों से जुड़ा हुआ है।
प्रेषित

6
यह केवल फ़ंक्शन के अंदर काम करता है, लेकिन प्रश्न निर्दिष्ट करता है कि फ़ंक्शन को नहीं बुलाया जाना चाहिए।
user2357112

5
यदि आप अपने फ़ंक्शन को कुछ अधिक उपयोग करने योग्य बनाना चाहते हैं और याद रखना आसान है तो यू को फ्रेम 1 को फिर से प्राप्त करना है sys._getframe(1).f_code.co_name, इसलिए आप किसी फ़ंक्शन को परिभाषित कर सकते हैं get_func_name()और फ़ंक्शन के वांछित नाम को प्राप्त करने की अपेक्षा कर सकते हैं ।
m3nda

44
my_function.func_name

कार्यों के अन्य मज़ेदार गुण भी हैं। dir(func_name)उन्हें सूचीबद्ध करने के लिए लिखें । func_name.func_code.co_codeसंकलित समारोह है, एक स्ट्रिंग के रूप में संग्रहीत।

import dis
dis.dis(my_function)

लगभग मानव पठनीय प्रारूप में कोड प्रदर्शित करेगा । :)


4
F .__ name__ और f.func_name में क्या अंतर है?
फेडेरिको ए। रामपोनी

14
सैम: नाम निजी हैं, __ नाम विशेष हैं, एक वैचारिक अंतर है।
मैथ्यू ट्रेवर

11
यदि कोई मैथ्यू द्वारा पूर्ववर्ती उत्तर को देखकर हैरान हो जाता है, तो टिप्पणी प्रणाली ने कुछ डबल-अंडरस्कोर की व्याख्या कोड के रूप में की है। बैकटिक के साथ भाग गए, संदेश को पढ़ना चाहिए: __names__निजी हैं, __namesविशेष हैं।
२१:१४

12
वास्तव में, मुझे लगता है कि सही _namesनिजी हैं (एकल अंडरस्कोर पहले, सिर्फ एक सम्मेलन), __names__विशेष हैं (पहले और बाद में डबल अंडरस्कोर)। यकीन नहीं है कि पहले डबल अंडरस्कोर का कोई अर्थ है, औपचारिक रूप से या एक सम्मेलन के रूप में।
मेस्ट्रेलेन

8
func_namepython3 में कोई भी अधिक मौजूद नहीं है, इसलिए func.__name__यदि आप संगतता चाहते हैं तो आपको उपयोग करने की आवश्यकता है
Daenyth

34

यह फ़ंक्शन कॉलर का फ़ंक्शन नाम वापस कर देगा।

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

यह फ्रेंडली रैपर के साथ अल्बर्ट वोनपुप के जवाब जैसा है।


1
मेरे पास इंडेक्स [2] में "<मॉड्यूल>" था, लेकिन निम्नलिखित ने काम किया: ट्रेसबैक.एक्सट्रेक्ट_स्टैक (कोई नहीं, २) [०] [- १]
इमामग्रस १ag'१४

3
मेरे लिए यह काम नहीं करता है, लेकिन यह करता है: ट्रेसबैक।
टेक्स्ट_स्टैक

यह काम करता है यदि पहली अनुक्रमणिका को 1 में बदल दिया जाए, तो आप लोगों को टिप्पणी करने से पहले डिबग करना सीखना चाहिए ... ट्रेसबैक.एक्सट्रेक्ट_स्टैक (कोई नहीं, 2) [1] [2]
Jcc.Sanabria

29

यदि आप कक्षा के तरीकों में भी रुचि रखते हैं, तो __qualname__इसके अलावा Python 3.3+ में भी है __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"

20

मुझे फंक्शन डेकोरेटर का उपयोग करना पसंद है। मैंने एक क्लास जोड़ी, जो फंक्शन टाइम का भी समय था। मान लें कि गॉग एक मानक अजगर लकड़हारा है:

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():

15

sys._getframe()अजगर के सभी कार्यान्वयन में उपलब्ध होने की गारंटी नहीं है ( देखें रेफरी ), आप tracebackएक ही काम करने के लिए मॉड्यूल का उपयोग कर सकते हैं , उदाहरण के लिए।

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

   return funcName

stack[-1]वर्तमान प्रक्रिया विवरण वापस करने के लिए एक कॉल ।


क्षमा करें, यदि sys._getframe()अपरिभाषित है, तो traceback.extract_stackनिष्क्रिय भी है। उत्तरार्द्ध पूर्व की कार्यक्षमता का एक मोटा सुपरसेट प्रदान करता है; आप एक दूसरे के बिना देखने की उम्मीद नहीं कर सकते। और वास्तव में, आयरनपिथॉन 2.7 में extract_stack()हमेशा लौटता है []। -1
सिंगलनेटाइजेशन इम्प्लाइज

15
import inspect

def foo():
   print(inspect.stack()[0][3])

कहाँ पे

  • ढेर () [को ०] बुलाने वाला

  • स्टैक () [3] विधि का स्ट्रिंग नाम


1
सादा और सरल। stack()[0]हमेशा फोन करने वाला, [3]विधि का स्ट्रिंग नाम होगा।
कांटूर

14

@ डेमनी के उत्तर के विस्तार के रूप में , मैंने कुछ उपयोगिता फ़ंक्शंस बनाए, जो वर्तमान फ़ंक्शन का नाम और वर्तमान फ़ंक्शन के तर्क मुद्रित करते हैं:

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)])

8

आप केवल फ़ंक्शन का नाम प्राप्त करना चाहते हैं, इसके लिए एक सरल कोड है। मान लें कि आपके पास ये कार्य परिभाषित हैं

def function1():
    print "function1"

def function2():
    print "function2"

def function3():
    print "function3"
print function1.__name__

आउटपुट function1 होगा

अब मान लीजिए कि आपके पास एक सूची में ये कार्य हैं

a = [function1 , function2 , funciton3]

कार्यों का नाम पाने के लिए

for i in a:
    print i.__name__

आउटपुट होगा

फ़ंक्शन 1
फ़ंक्शन 2
फ़ंक्शन 3


5

मैंने कुछ जवाब देखे हैं जो सज्जाकारों का उपयोग करते हैं, हालांकि मुझे लगा कि कुछ एक सा था। यहाँ कुछ मैं फ़ंक्शन नाम के साथ-साथ उनके संबंधित इनपुट और आउटपुट मान लॉगिंग के लिए उपयोग करता हूं। मैंने इसे केवल एक लॉग फ़ाइल बनाने के बजाय जानकारी प्रिंट करने के लिए यहाँ अनुकूलित किया है और इसे ओपी विशिष्ट उदाहरण पर लागू करने के लिए अनुकूलित किया है।

def debug(func=None):
    def wrapper(*args, **kwargs):
        try:
            function_name = func.__func__.__qualname__
        except:
            function_name = func.__qualname__
        return func(*args, **kwargs, function_name=function_name)
    return wrapper

@debug
def my_function(**kwargs):
    print(kwargs)

my_function()

आउटपुट:

{'function_name': 'my_function'}

1
अन्य सभी के विपरीत मुझे जो पसंद है, वह यह है कि debugफ़ंक्शन को एक बार जोड़कर आप केवल फ़ंक्शन को जो भी ज़रूरत है या फ़ंक्शन नाम प्रिंट करना चाहते हैं, उसे केवल डेकोरेटर जोड़कर कार्यक्षमता जोड़ सकते हैं। यह सबसे आसान और सबसे अनुकूलनीय लगता है।
अतिरिक्त समय
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.