在Python中,如何在不调用函数的情况下以字符串的形式获得函数名?

1

2

3

4def my_function():

pass

print get_function_name_as_string(my_function) # my_function is not in quotes

应该输出"my_function"。

Python中有这样的函数吗?如果没有,有关于如何在Python中实现get_function_name_as_string的想法吗?

stackoverflow.com/questions/245304/…

下次请在问题中加入你的动机。在当前的形式下,它显然使人们感到困惑,其中一些人倾向于假设您将逐字调用get_function_name_as_string(my_function)并期望得到"my_function"的结果。我猜您的动机是通用代码,它将函数作为第一类对象使用,并且需要检索作为参数传递的函数的名称。

问题背后的动机与技术答案无关。不要把它作为嘲笑、批评、理智的姿态和逃避回答的借口。

然而,动机可以帮助决定是否提出了正确的问题。在这个例子中,用户已经清楚地知道函数的名称,所以使用另一个函数来返回它?为什么不直接做一些像print("my_function")这样的事情呢?答案在于动机。

@Dannid,这是一个愚蠢的论点。如果OP要求获取函数的名称,是因为它是以需要输出的方式封装或理解的,例如为了调试的目的。在需要这种需求的环境中手工调整它是一种可怕的编程实践。您可能有一个要调用的函数列表,或者传递一个函数并希望记录函数名。除了为了好玩/学习Python之外,还有其他一百万个理由,如果你想学的话,这些理由已经足够了。

再读一遍我的评论,我不确定自己为什么会站在希望获得动力的一边。动力应该是无关紧要的。看来我是在替穷人说话。我认为我的感觉和沟通不是很好是它有助于知道什么是函数的目标-你调试吗?编写函数模板?创建动态全局变量?这是一个一次性的功能,还是一个您将经常使用的永久功能?无论如何,我应该同意动机与技术答案无关,尽管它可能有助于决定哪个技术答案是最好的。

事实上,动机是相关的,当你不清楚的时候,质疑它是至关重要的。但是关于嘲笑的建议是正确的。meta.stackexchange.com/questions/66377/what-is-the-xy-proble? & # 8203; m

1my_function.__name__

使用__name__是首选的方法,因为它的应用是一致的。与func_name不同的是,它也适用于内置函数:

1

2

3

4

5

6

7>>> import time

>>> time.time.func_name

Traceback (most recent call last):

File"", line 1, in ?

AttributeError: 'builtin_function_or_method' object has no attribute 'func_name'

>>> time.time.__name__

'time'

此外,双下划线向读者表明这是一个特殊的属性。另外,类和模块也有一个__name__属性,所以您只需要记住一个特殊的名称。

-1:您正在硬编码函数名。如果您已经知道函数名,为什么还要调用它的name属性呢?

因为在某些情况下,您会得到一些函数对象作为函数的参数,您需要显示/存储/操作该函数的名称。也许您正在生成文档、帮助文本、操作历史记录等等。不,你并不总是硬编码函数名。

@mgargiel:我的意思是:假设您有一个类,它定义了100个方法,其中所有方法都只是包装器,它们调用一个私有方法,传递包装器本身的名称。例如:def wrapper(kwargs): super(ExtendedClass,self).call('wrapper', kwargs)。您还有另一个选择,即:def wrapper(kwargs): super(ExtendedClass,self).call(sys._getframe().f_code.co_nam‌​e, kwargs)。所以Albert Vonpupp的答案在我看来更好。

@RichardGomes,一个答案适用于在函数本身中获取名称,另一个答案适用于从函数引用中获取名称。OP的问题表明了后者。

@RichardGomes,实际上我来这个问题是为了寻找解决这个问题的方法。我试图解决的问题是创建一个可用于记录所有调用的装饰器。

@RichardGomes函数是一类对象,可以有多个名称绑定到它们。这并不一定是f.__name__ == 'f'的情况。

这篇文章帮助我解决了这个问题。

这是我觉得唯一的线程,以赞成票反对以及澄清意见(即。,第一个和第二个):D

这是Stack Overflow的一个经典例子:"我不在乎你想做什么,我将拒绝给你答案,因为我不同意。"

我不认为这个解决方案有任何帮助,因为大多数人只有在他们想要一些通用的东西时才会使用它,而这些东西你可以多次调用作为一个方法。如果您想跟踪运行函数的顺序,那么这种方法是很好的。上面的解是,函数是foo,调用foo。然后将其设置为变量名。您还不如设置一个值为foo的字符串。下面描述的_getframe()调用是另一个解决方案,它在一个类中的多个函数中工作!正是我所需要的。

@EamonnKenny我写了一个装饰器,它接受一个泛型函数作为输入。在某些情况下,如果方法不受支持,则会引发错误。我的异常报告异常消息中不支持的方法名。__name__解决了这个问题。

哈哈因为@RichardGomes的恶意挑衅,它鼓励我投赞成票。

你也可以用

1

2import sys

this_function_name = sys._getframe().f_code.co_name

+1:这就是我想知道的答案。其他答案假设调用者已经知道函数名,这在这个问题的上下文中是无意义的。

理查德:没有。假设在函数定义的范围内直接调用函数name或func_name,但通常情况并非如此。请记住函数是对象——它们可以作为参数传递给其他函数,存储在列表/dict中,以便以后查找或执行,等等。

@ paulus_全能,深入堆栈框架并不会让我觉得抽象!事实上,它是抽象的对立面。请参阅文档中的实现细节说明。并不是所有的Python实现都包含sys._getframe——它直接连接到CPython的内部。

这只在函数内部有效,但是问题指定不应该调用函数。

如果你想把你的函数包装成更有用、更容易记住的东西,你必须检索像sys._getframe(1).f_code.co_name这样的帧1,这样你就可以定义像get_func_name()这样的函数,并期望得到调用函数的期望名称。

这正是我想要的。谢谢你!现在我应该更好地理解为什么它会起作用。

@Igor, sys._getframe(),获取一个n帧,case of sys._getframe(1)将从列表/堆栈中获取一个"one deep level"帧。因此,如果在类->函数->函数之间封装调用,则需要传递调用它的函数/类的数量。这有点奇怪,但很简单。在单个直接调用中,执行sys._getframe()意味着执行sys._getframe(0),因为没有明确地告诉您不能神奇地猜测您可以传递数字。不客气

1my_function.func_name

函数还有其他有趣的属性。键入dir(func_name)来列出它们。func_name.func_code.co_code是编译后的函数,存储为字符串。

1

2import dis

dis.dis(my_function)

将以几乎人类可读的格式显示代码。:)

f的差值是多少?__name__ f.func_name ?

它们是一样的。python.org/doc/2.5.2/ref/types.html #类型

双下划线名称传统上被认为是私有的,但从未强制执行。所以最好使用func_name,即使它们可能是相同的。

Sam:名字是私有的,名字是特殊的,有概念上的区别。

如果有人对Matthew前面的回答感到困惑,注释系统将一些双下划线解释为bold代码。用反号转义后,消息应该是:__names__是私有的,__names是特殊的。

@MatthewTrevor,你有参考资料吗?

实际上,我认为正确的是_names是私有的(前面有一个下划线,只是一个约定),__names__是特殊的(前面和后面有两个下划线)。不确定双下划线之前是否有任何意义,正式或作为惯例。

@MestreLion它的名字叫"名字乱改"。

没错,我忘了名字拼错了。因此,我认为最好的建议是:对"普通"私人成员使用约定(_name),因为__name受制于命名错误,而__name__可能是"特殊的",这取决于name,除非其中任何一个是您想要的,并且您知道自己在做什么。

func_name在python3中已经不存在了,所以如果你想要兼容性,你需要使用func.__name__

这个函数将返回调用者的函数名。

1

2

3def func_name():

import traceback

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

这就像阿尔伯特·冯普(Albert Vonpupp)用友好的包装给出的答案。

我在索引[2]处有"",但是下面的工作是有效的:回溯。extract_stack(没有,2)[0][1]

对我来说,这不起作用,但是这有作用:traceback.extract_stack()[-1][2]

如果将第一个索引更改为1,您应该在注释之前学会调试…回溯。extract_stack(没有,2)[1][2]

如果您也对类方法感兴趣,Python 3.3+除了__name__之外还有__qualname__。

1

2

3

4

5

6

7

8

9

10

11

12def 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"

这应该是我能接受的答案。

我喜欢使用函数装饰器。我添加了一个类,它也乘以函数时间。假设gLog是一个标准的python日志记录器:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18class 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

现在你要做的就是装饰它

1

2@func_timer_decorator

def my_func():

_getframe()不能保证在所有Python实现中都可用(参见参考资料),您可以使用回溯模块来做同样的事情,例如。

1

2

3

4

5

6import traceback

def who_am_i():

stack = traceback.extract_stack()

filename, codeline, funcName, text = stack[-2]

return funcName

调用stack[-1]将返回当前流程的详细信息。

抱歉,如果sys._getframe()是未定义的,那么traceback.extract_stack也是不可操作的。后者提供了前者功能的粗略超集;你不能期望看到一个没有另一个。实际上,在IronPython 2.7中,extract_stack()总是返回[]。1

作为@Demyn答案的扩展,我创建了一些实用函数来打印当前函数的名称和参数:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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

你只需要得到函数名这里有一个简单的代码。假设你定义了这些函数

1

2

3

4

5

6

7

8

9def function1():

print"function1"

def function2():

print"function2"

def function3():

print"function3"

print function1.__name__

输出将是function1

现在假设你有一个列表中的这些函数

1a = [function1 , function2 , funciton3]

获取函数的名称

1

2for i in a:

print i.__name__

输出将是

function1

function2

function3

1

2

3

4import inspect

def foo():

print(inspect.stack()[0][3])

python中用什么函数读取字符串_如何在Python中获得函数名作为字符串?相关推荐

  1. python画图将标题中有变量_如何在matplotlib中打印变量名作为标题

    在python中不可能轻松地获取变量的名称(请参见answer).对于在python中传递给函数的变量,有使用inspect.详细信息here和基于此answer的案例解决方案的复杂解决方案impor ...

  2. python使用加号运算符可以连接两个字符串_如何在Python连接两个字符串

    如何在Python连接两个字符串 Python字符串是Unicode字符的集合. Python提供了许多内置函数来进行字符串操作.字符串串联是一个字符串与另一字符串合并时的过程.可以通过以下方式完成. ...

  3. python的matplotlib库内的函数_如何在matplotlib中找到函数下面的区域?

    我是python和matplotlib库的新手,我试图在绘图中得到函数行下方的区域.我有一个变量a&amp:b,它在我的绘图中移动一个矩形.我也许可以使用原始数学来解决这个问题,但我想知道是否 ...

  4. python 读取文本文件_如何在Python中读取大文本文件

    python 读取文本文件 Python File object provides various ways to read a text file. The popular way is to us ...

  5. python一行输出多个数据_如何在Python中让两个print()函数的输出打印在一行内?

    1.两个连续的print()函数为什么在输出时内容会分行显示? 解:print()中有两个默认参数sep和end,其中sep是代替分隔符,end是代替末尾的换行符,默认使用','代替空格,且默认末尾加 ...

  6. python set 排序_python set 排序_如何在Python中使用sorted()和sort()

    点击"蓝字"关注我们 ?"Python基础知识" 大卫·丰达科夫斯基  著 18财税3班 李潇潇    译 日期:2019年5月6日 一. 使用sorted() ...

  7. golang 格式化字符串_如何在Go中格式化字符串

    golang 格式化字符串 As strings are often made up of written text, there are many instances when we may wan ...

  8. regexp 好汉字符串_如何在JavaScript中使用RegExp确认字符串的结尾

    regexp 好汉字符串 by Catherine Vassant (aka Codingk8) 由凯瑟琳·瓦森(Catherine Vassant)(又名Codingk8) 如何在JavaScrip ...

  9. java中转json字符串_如何在Java中转义JSON字符串-Eclipse IDE技巧

    java中转json字符串 在Java应用程序中工作或进行JSON解析时,通常很常见的做法是从某些资源(例如RESTful Web服务)中复制粘贴JSON字符串,然后使用Jackson库解析JSON. ...

最新文章

  1. matlab通信物理层仿真,通信小精灵(物理层仿真工具) 可计算仿真误码率、理论误...
  2. matlab中数据可视化,matlab的数据可视化
  3. 用 Flask 来写个轻博客 (10) — M(V)C_Jinja 常用过滤器与 Flask 特殊变量及方法
  4. 软考高项之沟通与干系人管理-背诵记忆
  5. 20100519 学习记录:asp CreateFolder/上传附件
  6. mybatis学习(10): sql server身份验证和windows身份验证
  7. Kubernetes各个组件的概念
  8. Java 泛型(1):基本原理
  9. Objective-C中的@Property详解
  10. “我在苹果商店下载了一个诈骗App,损失60万美金!”
  11. 详解CSS的Flex布局
  12. 【python工具】获取linux和windows系统指定接口的IP地址
  13. 10.Qt元素QTreeWidgetItem
  14. MDK/KEIL4/KEIL5 安装教程
  15. esp32语音播放天气预报
  16. excel表格xlsx密码强制解除手机,忘记excel表格xlsx密码如何找回?
  17. The Places of Our Lives: Visiting Patterns and Automatic Labeling from Longitudinal Smartphone Data
  18. Ubuntu下安装截图软件Shutter
  19. 英语单词之神祠aesthetic
  20. 网站图片尺寸规格设计指导

热门文章

  1. linux windows 互传文件
  2. Javascript 教程/速成/全面 /总结【含代码】
  3. 为LTO磁带而生的文件系统LTFS|主线任务—夺回“秋雅“
  4. Failure when receiving data from the peer
  5. 最牛X的一行代码:让你的支付宝余额变亿!
  6. Android安全检测 - 日志信息泄露
  7. 研究生自救指南-阅读论文篇
  8. 期货交易入门知识有哪些?
  9. 【论文翻译】Accurate and Efficient Stereo Matching via Attention Concatenation Volume(CVPR 2022)
  10. DAY17:弱口令的探测与测试