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

封装内存对象列表的Python函数返回空列表,直接运行代码正常的原因

问题描述

将一段用于获取并排序内存中对象及其占用大小的代码封装为memory_obj_list函数后,调用函数返回空列表,但直接运行原代码功能正常,请问差异原因是什么?

原代码(直接运行正常)

import sys

# 这些是IPython环境下常见的内置对象,包括你正在创建的这个变量
ipython_vars = ['In', 'Out', 'exit', 'quit', 'get_ipython', 'ipython_vars']

# 获取对象及其占用大小的排序后的列表
sorted([(x, sys.getsizeof(globals().get(x))/1e6) for x in dir() if not x.startswith('_') and x not in sys.modules and x not in ipython_vars], key=lambda x: x[1], reverse=True)

封装后的函数(调用返回空列表)

def memory_obj_list():
    import sys

    # 这些是IPython环境下常见的内置对象,包括你正在创建的这个变量
    ipython_vars = ['In', 'Out', 'exit', 'quit', 'get_ipython', 'ipython_vars']

    # 获取对象及其占用大小的排序后的列表
    a = sorted([(x, sys.getsizeof(globals().get(x))/1e6) for x in dir() if not x.startswith('_') and x not in sys.modules and x not in ipython_vars], key=lambda x: x[1], reverse=True)
    return(a)

调用方式

memory_obj_list()
原因分析

核心差异在于作用域的不同:

  • 原代码在全局作用域运行,dir()会列出当前全局环境下的所有变量名,globals()获取的是全局命名空间字典,因此能捕获到你在全局定义的各种对象。
  • 封装成函数后,函数内部的dir()(不带参数)默认返回的是函数局部作用域的变量名,也就是函数内定义的sys、ipython_vars、a这些。而过滤条件会排除掉模块(sys属于sys.modules)、ipython_vars列表里的名字,剩下的符合条件的变量名为空,最终返回空列表。
修复方案

修改函数,明确获取全局作用域的变量名和命名空间,替换掉函数内的局部dir()调用:

def memory_obj_list():
    import sys

    # 这些是IPython环境下常见的内置对象,包括你正在创建的这个变量
    ipython_vars = ['In', 'Out', 'exit', 'quit', 'get_ipython', 'ipython_vars']
    # 直接获取全局命名空间字典
    global_ns = globals()
    # 遍历全局命名空间的键,而非函数局部的变量名
    result = sorted(
        [(name, sys.getsizeof(global_ns[name])/1e6) 
         for name in global_ns 
         if not name.startswith('_') 
         and name not in sys.modules 
         and name not in ipython_vars],
        key=lambda x: x[1], 
        reverse=True
    )
    return result

这样函数就能正确捕获全局作用域的对象,和原代码运行效果一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 13:37:26