2

考虑下面的代码,它是我下面问题的一部分:

import functools

N = 3

class Struct:
    """Create an instance with argument=value slots.
    This is for making a lightweight object whose class doesn't matter."""
    def __init__(self, **entries):
        self.__dict__.update(entries)

    def __repr__(self):

        args = ['%s=%s' % (k, repr(v)) for (k, v) in vars(self).items()]
        return '\nStruct(%s)' % ', '.join(args)

def doit( move ):

    ( rowIn, colIn ) = move
    something = rowIn  + ( 10 * colIn ) # An involved computation here in real life

    return Struct( coord = ( rowIn, colIn ), something = something )

legalStates = [ ( row, col ) for row in xrange( N ) for col in xrange( N ) ] # A more complicated function that generates the list in real life. Call it 'complicatedFunction'

genExpFn = lambda : ( ( s.something, m, s ) for ( m, s ) in ( ( move, doit( move ) ) for move in legalStates ) )  #Q1

successorsSortedGenFn = lambda : ( p for p in sorted( genExpFn(), reverse = True ) )

def bFunc( s, a ):

    #print "a * s ->", a * s
    return a * s # An involved computation here in real life

def aFunc( ( v, m, s ) ): #Q2

    assert( s.something == v )
    return bFunc( s.something, 10 )

print "min( successorsSortedGen ) -> " + str( min( successorsSortedGenFn(), key=functools.partial( aFunc )) ) #Q3
print
print "max( successorsSortedGen ) -> " + str( max( successorsSortedGenFn(), key=functools.partial( aFunc )) ) #Q4

我的问题基于标记为“#Q”的陈述:

Q1:很明显,生成器已完全实例化(所有元素都被执行),正如我们调用sorted()它(它生成所有元素并创建一个临时未排序列表,它排序并作为新列表返回?)。

有没有一种节省空间的方法,可以最大限度地减少临时对象的创建产生排序列表?

我尝试过,但无法编写一个可以使用就地排序的列表理解list.sort()

这是我在想的那种表达方式:

successorsSorted = [ ( s.something, m, s ) for ( m, s ) in ( ( move, doit( move ) ) for move in legalStates ) ].sort( reverse = True )

Q2:请注意,'aFunc' 只是 'bFunc' 的包装,因为我无法在functools.partial( aFunc )调用中编写等效表示。

functools.partial( aFunc )我正在寻找的“aFunc”表达式是什么,可以让我直接调用“bFunc”


编辑:Q2 的答案是lambda ( v, m, s ): bFunc(s.something, 10)

因此,语句变为:

print "min( successorsSortedGen ) -> " + str( min( successorsSortedGenFn(), key=functools.partial( lambda ( v, m, s ): bFunc(s.something, 10)) ) )
print
print "max( successorsSortedGen ) -> " + str( max( successorsSortedGenFn(), key=functools.partial( lambda ( v, m, s ): bFunc(s.something, 10)) ) )

我知道这似乎有点蹩脚,我之前没有想到这个,但是哦,好吧(感谢 aaronasterling 的温和刺激)。


Q3, Q4:请注意,传递给 min() 和 max() 的元素已经排序。

我是否可以对 min() 和 max() 进行此提示,以便它不会将整个列表作为临时实例实例化,然后遍历整个列表以定位 min 或 max 元素?

如果没有,是否存在不实例化整个列表的模块或自定义函数,但是,鉴于传递给它的列表已排序,在检查最少数量的元素时返回最小或最大元素

4

1 回答 1

2

Q1。[x for x in somelist].sort()创建一个列表并调用该sort方法。这将返回None分配给 的None作业successorSorted。如果你想这样做,你必须自己实现它,它可能会比创建临时列表的内置排序慢得多。

Q2。您可以拆开代码对象并重新排列参数列表,使其a成为第一个参数,然后重写所有字节码以说明本地人的新位置。(是的,这实际上可以做到)。然后你可以使用functools.partial它。或者你可以像现在这样或以其他一些方式使用包装器。我在包装上 +1。(虽然如果你想要字节码破解,请告诉我,我认为它们很有趣,而且在 Stack Overflow 上提供它们作为答案的酷之处在于我可以编写它们但不必使用它们;)

第三季度,第四季度。并不真地。要获得迭代器的第十个元素,您需要遍历所有之前的元素。如果你知道你想要第一个元素,你可以这样做

smallest = next(sorted_iterator)

最后

for item in iterable: pass
largest = item

第一个会吃掉迭代器的第一个元素,最后一个会吃掉整个迭代器。再见迭代器。

于 2010-11-28T07:42:43.030 回答