স্ট্রিং হিসাবে একটি ফাংশন নাম পেতে কিভাবে?


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
কারণ কিছু ক্ষেত্রে, আপনি আপনার ফাংশনটির আর্গুমেন্ট হিসাবে কিছু ফাংশন অবজেক্ট পান এবং আপনাকে সেই ফাংশনের নাম প্রদর্শন / সঞ্চয় / পরিচালনা করতে হবে। সম্ভবত আপনি ডকুমেন্টেশন, সহায়তা পাঠ্য, ক্রিয়াকলাপের ইতিহাস ইত্যাদি তৈরি করছেন So সুতরাং না, আপনি সর্বদা ফাংশনটির নাম হার্ডকডিং করছেন না।
এমবারজিয়েল

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
@ রিচার্ডগমস একটি উত্তর ফাংশনটির মধ্যেই নাম পাওয়ার জন্য উপযুক্ত, অন্যটি কোনও ফাংশন রেফারেন্স থেকে এটি পাওয়ার জন্য উপযুক্ত। লিখিত হিসাবে ওপির প্রশ্নটি পরবর্তীকালের ইঙ্গিত দেয়।
রাসেল বোরোগোভ

22
@ রিচার্ডগমস আসলে আমি এই সমস্যার সমাধানের সন্ধান করতে এই প্রশ্নে এসেছি। আমি যে সমস্যার সমাধান করতে চাইছি তা হ'ল একটি ডেকোরেটর তৈরি করা যা আমার সমস্ত কলগুলিতে লগ করতে ব্যবহার করা যেতে পারে।
আলি-হুশাইন

23
@ রিচার্ডগমস ফাংশনগুলি প্রথম শ্রেণীর অবজেক্ট, তাদের কাছে নামের সাথে আবদ্ধ থাকতে পারে। অগত্যা ঘটনাটি এমন নয় f.__name__ == 'f'
উইম

298

বর্তমান ফাংশনটির বা পদ্ধতির নামটি এর ভিতরে থেকে পেতে, বিবেচনা করুন:

import inspect

this_function_name = inspect.currentframe().f_code.co_name

sys._getframeinspect.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
রিচার্ড: না, তা হয় না। আপনি ধরে নিচ্ছেন যে আপনি নিজের ফাংশনটিতে নাম বা ফানক_নামকে সরাসরি একই স্কোপে সংজ্ঞায়িত করেছিলেন, যা এটি প্রায়শই ক্ষেত্রে হয় না calling মনে রাখবেন যে ফাংশনগুলি
হ'ল

11
@ পলুস_মালিউটি, স্ট্যাক ফ্রেমের খনন আমাকে বিমূর্ত হিসাবে আঘাত করে না! আসলে, এটি বিমূর্ত বিপরীতে এক ধরণের। ডক্সে বাস্তবায়ন বিশদ নোটটি দেখুন । পাইথনের সমস্ত বাস্তবায়ন অন্তর্ভুক্ত নয় sys._getframe- এটি সিপিথনের অভ্যন্তরগুলির সাথে সরাসরি সংযুক্ত।
প্রেরক

6
এটি কেবল ফাংশনের অভ্যন্তরে কাজ করে, তবে প্রশ্নটি নির্দিষ্ট করে যে ফাংশনটি কল করা উচিত নয়।
ব্যবহারকারী 2357112 0: 02 তে মনিকা

5
আপনি যদি আপনার ফাংশনটি আরও ব্যবহারযোগ্য এবং সহজে মনে রাখতে পারেন যে আপনার ফ্রেম 1 টি পুনরুদ্ধার sys._getframe(1).f_code.co_nameকরতে হবে তবে আপনি যাতে কোনও ফাংশনটি সংজ্ঞায়িত করতে পারেন get_func_name()এবং যে ফাংশনটি শুরু করেছিলেন তার পছন্দসই নামটি পেতে পারেন expect
m3nda 10

44
my_function.func_name

ফাংশনগুলির অন্যান্য মজাদার বৈশিষ্ট্যও রয়েছে। dir(func_name)তাদের তালিকা করতে টাইপ করুন। func_name.func_code.co_codeএকটি সংকলিত ফাংশন, একটি স্ট্রিং হিসাবে সঞ্চিত।

import dis
dis.dis(my_function)

কোডটি প্রায় মানব পাঠযোগ্য বিন্যাসে প্রদর্শন করবে । :)


4
F .__ নাম__ এবং f.func_name এর মধ্যে পার্থক্য কী?
ফেডেরিকো এ রামপনি

14
স্যাম: নামগুলি ব্যক্তিগত, __ নামগুলি বিশেষ, একটি ধারণাগত পার্থক্য রয়েছে।
ম্যাথিউ ট্রেভর

11
ম্যাথু দ্বারা পূর্ববর্তী উত্তর দ্বারা কেউ বিস্মিত হলে, মন্তব্য সিস্টেমটি কিছু ডাবল-আন্ডারস্কোরকে সাহসের জন্য কোড হিসাবে ব্যাখ্যা করেছে। ব্যাকটিক দিয়ে পালানো, বার্তাটি পড়তে হবে: __names__ব্যক্তিগত, __namesবিশেষ।
বিশ্বব্যাপী

12
আসলে, আমি মনে করি সঠিকটি _namesব্যক্তিগত (একক আন্ডারস্কোর আগে, কেবল একটি সম্মেলন), __names__বিশেষ (পূর্বে এবং পরে ডাবল আন্ডারস্কোর)। আনুষ্ঠানিকভাবে বা কনভেনশন হিসাবে এর আগে ডাবল আন্ডারস্কোরটির কোনও অর্থ আছে কিনা তা নিশ্চিত নয়।
MestreLion

8
func_nameপাইথন 3-তে আর কোনও অস্তিত্ব নেই সুতরাং আপনি func.__name__যদি সামঞ্জস্যতা চান তবে আপনাকে ব্যবহার করতে হবে
দেনিথ

34

এই ফাংশনটি কলারের ফাংশনটির নাম ফিরিয়ে দেবে।

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

এটি বন্ধুত্বপূর্ণ মোড়ক দিয়ে আলবার্ট ভনপ্প্পের উত্তর মত।


1
সূচীতে আমার "<মডুল>" ছিল [2], তবে নিম্নলিখিতগুলি কাজ করেছে: traceback.extract_stack (কিছুই নয়, 2) [0] [- 1]
ইমমাগ্রাস

3
আমার জন্য এটি কাজ করে না, তবে এটি করে: traceback.extract_stack () [- 1] [2]
mike01010

এটি কাজ করে যদি প্রথম সূচকে 1 তে পরিবর্তন করা হয়, আপনার
ভাবা লোকদের

29

আপনি যদি শ্রেণিক পদ্ধতিতেও আগ্রহী হন, পাইথন ৩.৩++ __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"

20

আমি একটি ফাংশন ডেকোরেটর ব্যবহার করতে পছন্দ করি। আমি একটি ক্লাস যুক্ত করেছি, যা ফাংশনের সময়কেও দ্বিগুণ করে। ধরে নিন 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

সুতরাং এখন আপনার ফাংশনটির সাথে আপনাকে যা করতে হবে তা এটি সজ্জিত করা এবং ভয়েলা ila

@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আরো অস্ত্রোপচারের উপযোগী নয় এমন নয়। পরেরটির কার্যকারিতার মোটামুটি সুপারসেট সরবরাহ করে; আপনি অন্যটি ছাড়া একটি দেখার আশা করতে পারেন না। এবং আসলে, আয়রন পাইথনে ২.7 extract_stack()সর্বদা ফিরে আসে []। -1
সিঙ্গেল নেজেশন ইলিমিনেশন

15
import inspect

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

কোথায়

  • স্ট্যাক () [0] কলার

  • স্ট্যাক () [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__

আউটপুট ফাংশন 1 হবে

এখন বলুন যে আপনার তালিকায় এই ফাংশন রয়েছে

a = [function1 , function2 , funciton3]

ফাংশন নাম পেতে

for i in a:
    print i.__name__

আউটপুট হবে

ফাংশন 1
ফাংশন 2
ফাংশন 3


5

আমি কয়েকটি উত্তর দেখেছি যা সজ্জকারকে কাজে লাগিয়েছিল, যদিও আমি অনুভব করেছি যে কিছুটা কিছুটা ভার্জোজ ছিল। এখানে ফাংশন নামগুলি লগ করার পাশাপাশি তাদের সম্পর্কিত ইনপুট এবং আউটপুট মানগুলির জন্য আমি ব্যবহার করি use আমি একটি লগ ফাইল তৈরি করার চেয়ে তথ্য প্রিন্ট করার জন্য এটি এখানে রূপান্তরিত করেছি এবং ওপি নির্দিষ্ট উদাহরণটিতে প্রয়োগ করার জন্য এটি রূপান্তর করেছি।

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একবার আপনি ফাংশনটি যুক্ত করে কেবলমাত্র আপনার যা প্রয়োজন ফাংশনে ডেকরেটার যুক্ত করতে বা ফাংশনটির নাম মুদ্রণ করতে চান তা যুক্ত করে কার্যকারিতা যুক্ত করতে পারেন। এটি সবচেয়ে সহজ এবং সবচেয়ে অভিযোজ্য বলে মনে হচ্ছে।
স্পয়ারটাইমকোডার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.