Python算法挑战?

2024-06-29 01:11:10 发布

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

我有一个python函数(称之为myFunction),作为输入,得到一个数字列表,并在一个复杂的计算之后返回计算结果(这是一个数字)。在

函数如下所示:

def myFunction( listNumbers ):
    # initialize the result of the calculation
    calcResult = 0

    # looping through all indices, from 0 to the last one
    for i in xrange(0, len(listNumbers), 1):
        # some complex calculation goes here, changing the value of 'calcResult'

    # let us now return the result of the calculation
    return calcResult

我测试了这个函数,它按预期工作。在

通常,myFunction被提供一个listNumbers参数,其中包含5000000元素。正如你所料,计算需要时间。我需要这个函数尽快运行

挑战来了::假设现在的时间是凌晨5点,listNumbers中只包含499999值。也就是说,它的最后一个值是不可用的。此值将仅在早上6点提供。在

显然,我们可以做如下1st mode):等到6am。然后,将最后一个值追加到listNumbers,然后运行myFunction。这个解决方案可行,但是在myFunction返回计算结果之前,需要一段时间(因为我们需要从第一个元素开始处理整个数字列表)。记住,我们的目标是尽快在早上6点后得到结果。在

我在想一个更有效的方法来解决这个问题(2nd mode):因为(在早上5点)我们有listNumbers,里面有499999值,让我们立即开始运行myFunction。让我们处理所有我们能处理的数据(记住,我们还没有最后一块数据),然后——正好在早上6点——插入新的数据块——并生成计算结果。这应该要快得多,因为大部分处理都是在早上6点之前完成的,因此,我们只需要处理新的数据——这意味着计算结果应该在早上6点之后立即可用。在

假设我们没有办法检查myFunction的代码或修改它。是否有任何编程技术/设计思想允许我们将myFunction保持原样,并用它做一些事情(不改变其代码),这样我们就可以让它在第二种模式下运行,而不是第一种模式?在

请不要建议使用c++/numpy + cython/parallel computing等来解决这个问题。这里的目标是看看是否有任何编程技术设计模式可以轻松地用于解决此类问题。在


Tags: ofthe数据函数元素列表return时间
3条回答

您可以使用generator作为输入。只有当有数据可供处理时,生成器才会返回。在

更新:感谢您的精彩评论,我想删除此条目:)

class lazylist(object):
    def __init__(self):
        self.cnt = 0
        self.length = 5000000

    def __iter__(self):
        return self

    def __len__(self):
        return self.length

    def next(self):
        if self.cnt < self.length:
            self.cnt += 1
            #return data here or wait for it
            return self.cnt #just return a counter for this example
        else:
            raise StopIteration()

    def __getitem__(self, i):
        #again, block till you have data.
        return i+1 #simple counter

myFunction(lazylist())

更新:正如您从注释和其他解决方案中看到的,您的循环构造和len调用会引起很多麻烦,如果您能够消除它,您可以使用更优雅的解决方案。for e in li或{}是Python的方式。在

子类列表,以便在函数尝试读取最后一个值时阻塞,直到另一个线程提供该值。在

import threading
import time

class lastblocks(list):
    def __init__(self,*args,**kwargs):
        list.__init__(self,*args,**kwargs)
        self.e = threading.Event()
    def __getitem__(self, index):
        v1 = list.__getitem__(self,index)
        if index == len(self)-1:
            self.e.wait()
            v2 = list.__getitem__(self,index)
            return v2
        else:
            return v1


l = lastblocks(range(5000000-1)+[None])

def reader(l):
    s = 0
    for i in xrange(len(l)):
        s += l[i]
    print s

def writer(l):
    time.sleep(10)
    l[5000000-1]=5000000-1
    l.e.set()
    print "written"

reader = threading.Thread(target=reader, args=(l,))
writer = threading.Thread(target=writer, args=(l,))
reader.start()
writer.start()

印刷品:

^{pr2}$

对于numpy:

import threading
import time

import numpy as np

class lastblocks(np.ndarray):
    def __new__(cls, arry):
        obj = np.asarray(arry).view(cls)
        obj.e = threading.Event()
        return obj
    def __array_finalize__(self, obj):
        if obj is None: return
        self.e = getattr(obj, 'e', None)

    def __getitem__(self, index):
        v1 = np.ndarray.__getitem__(self,index)
        if index == len(self)-1:
            self.e.wait()
            v2 = np.ndarray.__getitem__(self,index)
            return v2
        else:
            return v1


l = lastblocks(np.asarray(range(5000000-1)+[None]))

def reader(l):
    s = 0
    for i in xrange(len(l)):
        s += l[i]
    print s

def writer(l):
    time.sleep(10)
    l[5000000-1]=5000000-1
    l.e.set()
    print "written"

reader = threading.Thread(target=reader, args=(l,))
writer = threading.Thread(target=writer, args=(l,))
reader.start()
writer.start()

你所说的“数字列表”是指一个实际的内置list类型吗?在

  • 如果没有,就很简单。Python使用duck类型,因此传递任何支持迭代的序列都可以。使用yield关键字传递generator。在

    def delayed_list():
        for val in numpy_array[:4999999]:
            yield val
        wait_until_6am()
        yield numpy_array[4999999]
    

然后

^{pr2}$
  • 如果是,那就更棘手了:)

另外,请查看PEP8以获得推荐的Python代码样式:

  • 括号内无空格
  • my_function而不是{}
  • for i, val in enumerate(numbers):而不是{}等

相关问题 更多 >