Python高级技巧:用一行代码减少一半内存占用
文章插图
来源:大数据文摘(ID:BigDataDigest)
内存不足是项目开发过程中经常碰到的问题 , 我和我的团队在之前的一个项目中也遇到了这个问题 , 我们的项目需要存储和处理一个相当大的动态列表 , 测试人员经常向我抱怨内存不足 。 但是最终 , 我们通过添加一行简单的代码解决了这个问题 。
结果如图所示:
文章插图
我将在下面解释它的工作原理 。
举一个简单的“learning”示例 - 创建一个DataItem类 , 在其中定义一些个人信息属性 , 例如姓名 , 年龄和地址 。
class DataItem(object):def __init__(self, name, age, address):self.name = nameself.age = ageself.address = address
小测试——这样一个对象会占用多少内存?
首先让我们尝试下面这种测试方案:
d1 = DataItem("Alex", 42, "-")print ("sys.getsizeof(d1):", sys.getsizeof(d1))
答案是56字节 。 看起来比较小 , 结果令人满意 。
但是 , 让我们检查另一个数据多一些的对象:
d2 = DataItem("Boris", 24, "In the middle of nowhere")print ("sys.getsizeof(d2):", sys.getsizeof(d2))
答案仍然是56 。 这让我们明白这个结果并不完全正确 。
我们的直觉是对的 , 这个问题不是那么简单 。 Python是一种非常灵活的语言 , 具有动态类型 , 它在工作时存储了许多额外的数据 。 这些额外的数据本身就占了很多内存 。
例如 , sys.getsizeof(“ ”)返回33 , 没错 , 每个空行就多达33字节!并且sys.getsizeof(1)将为此数字返回24-24个字节(我建议C程序员们现在点击结束阅读 , 以免对Python的美丽失去信心) 。
对于更复杂的元素 , 例如字典 , sys.getsizeof(dict)返回272个字节 , 这还只是一个空字典 。 举例到此为止 , 但事实已经很清楚了 , 何况RAM的制造商也需要出售他们的芯片 。
现在 , 让我们回到回到我们的DataItem类和“小测试”问题 。
这个类到底占多少内存?
首先 , 我们将以较低级别输出该类的全部内容:
def dump(obj):for attr in dir(obj):print(" obj.%s = %r" % (attr, getattr(obj, attr)))
这个函数将显示隐藏在“隐身衣”下的内容 , 以便所有Python函数(类型 , 继承和其他包)都可以运行 。
结果令人印象深刻:
文章插图
它总共占用多少内存呢?
在GitHub上 , 有一个函数可以计算实际大小 , 通过递归调用所有对象的getsizeof实现 。
【Python高级技巧:用一行代码减少一半内存占用】def get_size(obj, seen=None):# From # Recursively finds size of objectssize = sys.getsizeof(obj)if seen is None:seen = setobj_id = id(obj)if obj_id in seen:return 0# Important mark as seen *before* entering recursion to gracefully handle# self-referential objectsseen.add(obj_id)if isinstance(obj, dict):size += sum([get_size(v, seen) for v in obj.values()])size += sum([get_size(k, seen) for k in obj.keys()])elif hasattr(obj, '__dict__'):size += get_size(obj.__dict__, seen)elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)):size += sum([get_size(i, seen) for i in obj])return size
让我们试一下:
d1 = DataItem("Alex", 42, "-")print ("get_size(d1):", get_size(d1))d2 = DataItem("Boris", 24, "In the middle of nowhere")print ("get_size(d2):", get_size(d2))
- 教你点开微信右上角,除了看街景知道哪儿人多,还隐藏5个技巧
- 大一上学期学了Python,希望主攻大数据还应该学习什么语言
- 从运维岗转向开发岗,该选择学习Java还是Python
- 「听」上海有望诞生首位快递工程高级工程师
- 你真的会用华为手机吗?10个EMUI使用技巧,你未必全知道
- 点赞!上海评出首位快递高级工程师
- 上海评出首位快递高级工程师
- 手机内存不足别乱删,学会这5个技巧,让手机释放大量空间
- 计算机专业大一下学期,该选择学习Java还是Python
- 华为认证HCIP-GaussDB-OLTP发布,下一个高级DBA会是你吗