You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何在函数内部获取调用方函数的唯一内存地址

实现方案

直接靠inspect拿栈帧就能取到,不需要绕弯子用函数名反查。核心是要避开实例/类方法生成临时绑定方法的坑——直接对临时生成的绑定方法取id拿到的是每次都变的无效值,必须拿到绑定方法包裹的原始函数对象,取到的id才是稳定唯一的内存地址,全局函数、类静态函数、实例方法、类方法、嵌套函数都能覆盖。

工具函数代码

import inspect
from typing import Optional

def get_caller_func_address() -> Optional[int]:
    # 栈层级说明:0是当前工具函数自身,1是调用本工具的业务函数,2是目标调用方
    stack = inspect.stack()
    if len(stack) < 3:
        return None
    caller_frame = stack[2].frame
    target_code = caller_frame.f_code

    # 先从全局命名空间匹配对应代码对象的原始函数
    for obj in caller_frame.f_globals.values():
        if getattr(obj, '__code__', None) is target_code:
            return id(obj)

    # 再从局部命名空间匹配,覆盖类内定义、嵌套函数场景
    for obj in caller_frame.f_locals.values():
        # 剥离绑定方法外壳,拿到原始函数
        raw_func = getattr(obj, '__func__', obj)
        if getattr(raw_func, '__code__', None) is target_code:
            return id(raw_func)

    # 兜底匹配类命名空间里的方法
    if 'self' in caller_frame.f_locals:
        cls = caller_frame.f_locals['self'].__class__
        for obj in cls.__dict__.values():
            raw_func = getattr(obj, '__func__', obj)
            if getattr(raw_func, '__code__', None) is target_code:
                return id(raw_func)
    if 'cls' in caller_frame.f_locals:
        cls = caller_frame.f_locals['cls']
        for obj in cls.__dict__.values():
            raw_func = getattr(obj, '__func__', obj)
            if getattr(raw_func, '__code__', None) is target_code:
                return id(raw_func)
    return None

效果验证

def func1():
    print(f"func1内获取到的调用方地址: {hex(get_caller_func_address())}")
    return 1

class A:
    @staticmethod
    def func2():
        print(f"func2内获取到的调用方地址: {hex(get_caller_func_address())}")
        return 2

    def func3(self):
        print(f"func3内获取到的调用方地址: {hex(get_caller_func_address())}")
        return 3
    
    @classmethod
    def func4(cls):
        print(f"func4内获取到的调用方地址: {hex(get_caller_func_address())}")
        return 4

# 打印各函数的基准内存地址做对比
print('func1基准地址:', hex(id(func1)))
print('func2基准地址:', hex(id(A.func2)))
print('func3基准地址:', hex(id(A.func3)))
print('func4基准地址:', hex(id(A.func4)))

# 构造调用链测试
def test_entry():
    print("test_entry自身地址:", hex(id(test_entry)))
    func1()
    A.func2()
    a = A()
    a.func3()
    A.func4()

test_entry()

运行后可以看到,工具函数拿到的调用方地址和提前打印的基准地址完全一致,不会出现实例方法id随调用漂移的问题。

注意事项

  • 禁止直接对临时生成的绑定方法取id,绑定方法是随访问临时生成的对象,调用结束就会被回收,id会被重复复用,不具备唯一性
  • id()返回的地址是Python对象生命周期内的唯一标识,只要函数对象没有被销毁,这个地址就不会变化
  • 装饰器包裹的函数如果要拿到原始函数地址,需要自行通过__wrapped__属性剥离装饰器层,逻辑和处理绑定方法一致

内容的提问来源于stack exchange,提问作者user16004728

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 15:31:15