以节省内存的方式聚合对象属性的python方法?

2024-09-30 12:15:06 发布

您现在位置:Python中文网/ 问答频道 /正文

例如,我们有大量这样的对象:

class KeyStatisticEntry:
    def __init__(self, value=""):
        self.usedBytes = len(value)
        self.encoding = get_string_encoding(value)

    @property
    def total(self):
        overhead = get_object_overhead(self.usedBytes)
        if self.encoding == 'some value':
            return overhead
        else:
            return self.usedBytes + overhead
    @property
    def aligned(self):
        return some_func_with(self.usedBytes)

    # Here is lots of calculated properties on basis of existing properties

我们需要收集大量关于这个obejct的度量-it属性的最小值、最大值、总和、平均值、标准偏差值。目前我使用的代码如下:

^{pr2}$

问题:

这里有没有更“Python”的方式,性能和内存利用率更好?在


Tags: of对象selfgetreturnvaluedefproperty
2条回答

您可以使用operator.attrgetter来获取对象的多个属性,然后使用itertools.zip_longest(python2.X中的itertools.izip_longest)将相关属性附加在一起。在

from operator import attrgetter
all_result = [attrgetter('usedBytes','total','aligned','encoding')(obj) for obj in keys.items()]

或者使用生成器表达式来创建生成器而不是列表:

^{pr2}$

然后使用zip_longest

used_bytes, total_bytes, aligned_bytes, encodings = zip_longest(*all_results)

然后使用map函数对需要求和的iterables应用sum函数:

used_user, used_real, aligned = map(sum,(used_bytes, total_bytes, aligned_bytes))

分别为len和{}:

total_elements = len(used_bytes)
mean = statistics.mean(used_bytes)

如果您想将所有子列表作为生成器处理(在内存使用方面更优化,而在运行时方面性能更低),则可以使用新类,以便使用生成器分别计算所需结果:

from itertools import tee
class Aggregator:
    def __init__(self, all_obj):
        self.obj = all_obj
        self.used_user, self.mean = self.getTotalBytesAndMean()
        self.total_elements = len(self.all_obj)
        self.aligned = self.getAligned()

    def getTotalBytesAndMean(self):
        iter_1, iter_2 = tee((obj.usedBytes for obj in self.all_obj))
        return sum(iter_1), statistics.mean(iter_2)

    def getTotal(self):
        return sum(obj.total for obj in self.all_obj)

    def getAligned(self):
        return sum(obj.aligned for obj in self.all_obj)

    def getEncoding(self):
        return (obj.encoding for obj in self.all_obj)

然后您可以:

Agg = Aggregator(keys.items())

# And simply access to attributes
Agg.used_user

可能有一种更好的内存使用方法,使用(隐式)生成器而不是列表来获取所有信息。我不确定如果您在同一个列表上进行许多计算(例如usedBytes),会不会更好。但是请注意,您不能在生成器上使用len(但是长度无论如何都是输入列表的长度):

total_elements = len(keys.items())
used_user = sum(obj.usedBytes for obj in keys.items())
used_real = sum(obj.total for obj in keys.items())
aligned = sum(obj.aligned for obj in keys.items())
mean = statistics.mean(obj.usedBytes for obj in keys.items())

相关问题 更多 >

    热门问题