Skip to main content
 首页 » 编程设计

python之任何存在内存使用的对象,如生成器,但可以在必要时返回一个 numpy 数组

2025年05月04日26Free-Thinker

我有一些时间数据,从 T0 开始,以 dt 为步长到达 T1。此数据以 dt 的小增量递增,目前存储为 numpy 数组,因此占用大量空间。一种更有效的存储方式是存储 T0、T1 和 dt,例如使用发电机。然而,生成器不适用于许多功能,例如numpy 函数、算术和绘图。我想要一些像生成器一样工作的东西,即只存储 3 个必要的值,然后在必要时生成一个 numpy 数组以用于某些函数等。

是否有任何已经存在的对象可以像这样工作? IE。将必要的数据(3 个值)存储在生成器中,然后在函数或算术中使用时将其自身返回/表示为一个 numpy 数组?内存只会在函数范围内使用,并在超出范围时释放。

编辑解决方案:我创建了一个我想要的实现。事实证明复制生成器很棘手,请参阅 here ,所以我改为存储开始、停止和步骤,并根据需要创建和返回生成器或 numpy 数组。

代码如下:

import numpy as _np 
 
class frange(): 
    """ 
    Return an object can be used to generate a generator or an array  
    of floats from start (inclusive) to stop (exclusive) by step.  
    This object stores the start, stop, step and length of 
    the data. Uses less memory than storing a large array. 
 
    Example 
    ------- 
    An example of how to use this class to generate some data is 
    as follows for some time data between 0 and 2 in steps of 
    1e-3 (0.001):: 
 
        $ time = frange(0, 2, 1e-3) 
 
        $ printlen(time) # prints length of frange, just like an array or list 
 
        $ generator = time.get_generator() # gets a generator instance 
        $ for i in generator: # iterates through printing each element 
        $     print(i) 
 
        $ array = time.get_array() # gets an array instance 
        $ newarray = 5 * array # multiplies array by 5 
 
 
    """ 
    def __init__(self, start, stop, step): 
        """ 
        Intialises frange class instance. Sets start, top, step and  
        len properties. 
 
        Parameters 
        ---------- 
        start : float 
            starting point 
        stop : float 
            stopping point  
        step : float 
            stepping interval 
        """ 
        self._slice = slice(start, stop, step) 
        self.len = self.get_array().size 
        return None 
 
    def get_generator(self): 
        """ 
        Returns a generator for the frange object instance. 
 
        Returns 
        ------- 
        gen : generator 
            A generator that yields successive samples from start (inclusive) 
            to stop (exclusive) in step steps. 
        """ 
        s = self._slice 
        gen = drange(s.start, s.stop, s.step) # intialises the generator 
        return gen 
 
    def get_array(self): 
        """ 
        Returns an numpy array containing the values from start (inclusive) 
        to stop (exclusive) in step steps. 
 
        Returns 
        ------- 
        array : ndarray 
            Array of values from start (inclusive) 
            to stop (exclusive) in step steps. 
        """ 
        s = self._slice         
        array = _np.arange(s.start, s.stop, s.step) 
        return array 
 
    def __len__(self): 
        return self.len       
 
def drange(start, stop, step): 
    """ 
    A generator that yields successive samples from start (inclusive) 
    to stop (exclusive) in step intervals. 
 
    Parameters 
    ---------- 
    start : float 
        starting point 
    stop : float 
        stopping point  
    step : float 
        stepping interval 
 
    Yields 
    ------ 
    x : float 
        next sample 
    """ 
    x = start 
    if step > 0: 
        while x + step <= stop: # produces same behaviour as numpy.arange 
            yield x 
            x += step 
    elif step < 0: 
        while x + step >= stop: # produces same behaviour as numpy.arange 
            yield x 
            x += step 
    else: 
        raise ZeroDivisionError("Step must be non-zero") 

请您参考如下方法:

Python 已经有一个存储start, stop, step 属性的类,一个slice

In [523]: s = slice(0, 1, .1) 

np.lib.index_tricks 有一个可以扩展切片的类。在这种情况下,它使用 arange:

In [524]: np.r_[s] 
Out[524]: array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9]) 
In [525]: np.arange(s.start, s.stop, s.step) 
Out[525]: array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9]) 
In [526]: np.arange(0, 1, .1) 
Out[526]: array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9]) 

slice 只是存储它的属性;任何计算都是由使用它的代码完成的。如果 step 值是虚数,np.r_ 使用这个技巧来调用 np.linspace。

In [527]: np.r_[slice(0,1,11j)] 
Out[527]: array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ]) 

我看不出另一个答案中讨论的生成器与动态运行 arange 或 linspace 相比有何改进。

如果您正在开发自己的索引类,那么值得您研究一下 index_tricks.py 文件。