函数有通用方式自我引用吗?

47 投票
4 回答
19465 浏览
提问于 2025-04-16 12:12

我可以通过下面的代码在一个Python函数内部访问它的属性:

def aa():
    print aa.__name__
    print aa.__hash__
    # other simliar

但是,如果上面的 aa() 函数是用来写其他代码的模板,比如 bb(),我就必须写:

def bb():
    print bb.__name__
    print bb.__hash__
    # other simliar

有没有类似于类方法中 self 参数的“指针”,这样我就可以像这样写代码?

def whatever():
    print self.__name__
    print self.__hash__
    # other simliar

我搜索了一下,发现有人说可以用类来解决这个问题,但这样可能需要重新定义所有现有的函数。这有什么建议吗?

4 个回答

0

你可以在第一行写 self = bb,这样当你改函数名字的时候,只需要改这一行,而不是每个地方都改。

我的代码编辑器会把变量 self 和类的高亮显示方式一样对待。

20

http://docs.python.org/library/inspect.html 这个链接看起来很有用:

import inspect
def foo():
     felf = globals()[inspect.getframeinfo(inspect.currentframe()).function]
     print felf.__name__, felf.__doc__

你还可以使用 sys 模块来获取当前函数的名字:

import sys
def bar():
     felf = globals()[sys._getframe().f_code.co_name]
     print felf.__name__, felf.__doc__
37

没有一种通用的方法让一个函数能自我引用。可以考虑使用装饰器来解决这个问题。如果你只是想打印一些关于这个函数的信息,使用装饰器就能很简单地做到:

from functools import wraps
def showinfo(f):
    @wraps(f)
    def wrapper(*args, **kwds):
         print(f.__name__, f.__hash__)
         return f(*args, **kwds)
    return wrapper

@showinfo
def aa():
    pass

如果你真的需要引用这个函数,那就把它作为函数的参数添加进去:

def withself(f):
    @wraps(f)
    def wrapper(*args, **kwds):
        return f(f, *args, **kwds)
    return wrapper

@withself
def aa(self):
      print(self.__name__)
      # etc.

编辑以添加备用装饰器

你还可以写一个更简单(可能更快)的装饰器,这样被装饰的函数就能正确地与Python的自省功能配合使用:

def bind(f):
    """Decorate function `f` to pass a reference to the function
    as the first argument"""
    return f.__get__(f, type(f))

@bind
def foo(self, x):
    "This is a bound function!"
    print(self, x)


>>> foo(42)
<function foo at 0x02A46030> 42
>>> help(foo)
Help on method foo in module __main__:

foo(self, x) method of builtins.function instance
    This is a bound function!

这利用了Python的描述符协议:函数有一个__get__方法,用于创建绑定方法。这个装饰器简单地使用现有的方法,让函数成为它自己的绑定方法。它只适用于独立的函数,如果你想让一个方法能够引用自己,就需要做一些更复杂的事情,类似于最初的解决方案。

撰写回答