我想要像
这样的东西def x():
print get_def_name()
但不一定知道x
的名称。
理想情况下,它会返回'x'
,其中x将是函数的名称。
答案 0 :(得分:7)
Python中的函数是对象,当这些对象发生时,它们的属性包含它们所定义的名称:
>>> def x():
... pass
...
>>> print x.__name__
x
所以,一种天真的方法可能就是这样:
>>> def x():
... print x.__name__
...
>>> x()
x
这似乎有效。但是,由于你必须知道函数内部x
的名称才能做到这一点,你还没有真正获得任何东西;你可能已经做到了这一点:
def x():
print "x"
事实上,它比这更糟糕,因为__name__
属性仅指函数定义的名称。如果它被绑定到另一个名称,它将不会按预期运行:
>>> y = x
>>> y()
x
更糟糕的是,如果原始名称不再存在,则根本不起作用:
>>> del x
>>> y()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in x
NameError: global name 'x' is not defined
第二个问题是你可以实际解决的问题,虽然它并不漂亮。诀窍是编写一个可以将函数名称作为参数传递给它的装饰器:
>>> from functools import wraps
>>> def introspective(func):
... __name__ = func.__name__
... @wraps(func)
... def wrapper(*args, **kwargs):
... return func(__name__=__name__, *args, **kwargs)
... return wrapper
...
>>> @introspective
... def x(__name__):
... print __name__
...
>>> x()
x
>>> y = x
>>> y()
x
>>> del x
>>> y()
x
...虽然你可以看到,你仍然只是回到了定义函数的名称,而不是现在碰巧绑定的名称。
在实践中,简短(和正确)的答案是“不要那样做”。 Python的一个基本事实是,对象不知道它们是什么名称(或名称)必然 - 如果你认为你的功能需要这些信息,你就会做错事。
答案 1 :(得分:2)
您可以使用Python的内置检查库来做到这一点。
如果您想处理更复杂的情况,可以阅读其更多文档,但是此代码段对您有用:
from inspect import getframeinfo, currentframe
def test_func_name():
return getframeinfo(currentframe()).function
print(test_func_name())
答案 2 :(得分:0)
这听起来像是要声明一个匿名函数,它会返回对新函数对象的引用。
在Python中,您可以使用lambda
获得一个简单的匿名函数对象,但对于复杂函数,它必须具有名称。但是任何函数对象实际上都是一个对象,您可以将引用传递给它,因此名称并不重要。
# lambda
sqr = lambda n: n**2
assert sqr(2) == 4
assert sqr(3) == 9
# named function
def f(n):
return n**2
sqr = f
assert sqr(2) == 4
assert sqr(3) == 9
请注意,此函数的名称为f
,但名称在此处并不重要。我们将名称sqr
设置为函数对象引用并使用该名称。如果我们愿意,我们可以将函数引用放入列表或其他数据结构中。
您可以重复使用该功能的名称:
def f(n):
return n**2
sqr = f
def f(n):
return n**3
cube = f
因此,虽然Python并不真正支持完整的匿名函数,但您可以获得相同的效果。你必须给函数命名,这不是一个真正的问题。
如果您真的不希望该功能有名称,您可以取消绑定名称:
def f(n):
return n**2
lst = [f] # save function reference in a list
del(f) # unbind the name
现在访问此功能的唯一方法是通过列表;函数的名称已经消失。