MST

星途 面试题库

面试题:Python模块多类存储与性能优化

当Python模块中存在大量相关的类,例如100个以上,这些类会频繁地被创建实例和销毁。请阐述如何对这些类的存储方式进行优化,以提高内存使用效率和程序运行性能。可以从模块结构设计、类的属性和方法定义、实例化过程等方面进行分析,并给出可能的实现思路或代码示例。
33.0万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

模块结构设计

  1. 分组模块:将相关功能的类划分到不同的子模块中。例如,按业务功能划分,如用户相关类放在 user_module,订单相关类放在 order_module。这样不仅便于管理,而且在导入模块时,只加载需要的部分,减少内存占用。
# user_module.py
class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

# main.py
from user_module import User
  1. 延迟加载:使用 importlib 实现延迟加载,只有在真正需要某个类时才加载。
import importlib

def get_user_class():
    module = importlib.import_module('user_module')
    return getattr(module, 'User')

User = get_user_class()
user = User('John', 25)

类的属性和方法定义

  1. 使用 __slots__:如果类的实例属性是固定的,使用 __slots__ 可以节省内存。它会为实例分配固定的内存空间,而不是使用字典来存储属性。
class MyClass:
    __slots__ = ['attr1', 'attr2']
    def __init__(self, attr1, attr2):
        self.attr1 = attr1
        self.attr2 = attr2
  1. 类方法和静态方法:如果方法不需要访问实例属性,定义为类方法或静态方法。这样方法存储在类级别,而不是每个实例都有一份拷贝。
class MathUtils:
    @staticmethod
    def add(a, b):
        return a + b

    @classmethod
    def multiply(cls, a, b):
        return a * b

实例化过程

  1. 对象池:使用对象池模式,预先创建一定数量的实例对象,需要时从池中获取,使用完后放回池中,避免频繁的创建和销毁。
class ObjectPool:
    def __init__(self, cls, pool_size=10):
        self.cls = cls
        self.pool = [cls() for _ in range(pool_size)]

    def get_object(self):
        if self.pool:
            return self.pool.pop()
        return self.cls()

    def return_object(self, obj):
        self.pool.append(obj)


class MyObject:
    pass


pool = ObjectPool(MyObject)
obj = pool.get_object()
# 使用obj
pool.return_object(obj)
  1. 弱引用:如果存在对象之间的循环引用,使用弱引用避免内存泄漏。例如,在缓存场景中,缓存对象对实际对象使用弱引用,当实际对象不再被其他地方引用时,可被垃圾回收。
import weakref


class BigData:
    def __init__(self, data):
        self.data = data


class Cache:
    def __init__(self):
        self.cache = {}

    def add_to_cache(self, key, obj):
        self.cache[key] = weakref.ref(obj)

    def get_from_cache(self, key):
        ref = self.cache.get(key)
        if ref:
            return ref()
        return None


data = BigData([1, 2, 3, 4, 5])
cache = Cache()
cache.add_to_cache('data_key', data)
retrieved_data = cache.get_from_cache('data_key')