【问题标题】:Odd Python zip() behavior奇怪的 Python zip() 行为
【发布时间】:2016-01-09 22:07:27
【问题描述】:

我正在使用 Python 中的生成器,但我的行为很奇怪。我不完全是如何表达这个问题的......

我的代码对目标函数执行模式搜索。我看到的问题出现在我 zip 我的 patternSearch 生成器的结果与 xrange 只获得前 12 个结果时。似乎我的生成器返回的元组的 xmin 组件在 zip 的长度上重复。特别奇怪的是,同一个元组的ymin 组件没有重复。当我初始化一个生成器对象ps并反复调用ps.next()时,结果是正确的。

可能是什么问题?谢谢!

代码

#!/usr/bin/env python2.7

def obj(x):
   x1,x2 = x
   return 100*(x2 - x1**2)**2 + (1 - x1)**2

# fobj: objective function of vector x
#   x0: initial point
#    h: initial step size
#    r: reduction parameter
def patternSearch(fobj,x0,h,r):
   n = len(x0) # get dimensionality
   dims = range(0,n)
   # initialize given x0
   xmin = list(x0)
   ymin = fobj(xmin)

   yield (xmin,ymin) # send back the initial condition first

   while True:
      focus = True
      for i in dims:
         x = xmin # start from the last best point
         x[i] += h
         y = fobj(x) # eval
         if y < ymin:
            ymin = y
            xmin = x
            focus = False
            continue
         # else, y > ymin
         x[i] -= 2*h # go in the opposite direction
         y = fobj(x) # eval
         if y < ymin:
            ymin = y
            xmin = x
            focus = False
            continue
         # else, no update to this dim
      if focus:
         h *= r
      yield (xmin,ymin)

def main():
   x0 = (3,5)
   imax = 12
   print 'Initial condition: ', x0
   print 'Stop condition: i == ', imax
   print 'Iteration |     x1     |     x2     |      y     '
   for (x,y), i in zip(patternSearch(obj,x0,h=0.5,r=0.5), xrange(imax)):
      print "{:>9} | {:<10} | {:<10} | {:<11}".format(i,x[0],x[1],y)

   print 'Generator output test:'
   g = patternSearch(obj,x0,0.5,0.5)
   for i in xrange(imax):
      g.next()

输出

Initial condition:  (3, 5)
Stop condition: i ==  12
Iteration |     x1     |     x2     |      y     
        0 | 2.0        | 4.03125    | 1604       
        1 | 2.0        | 4.03125    | 58.5       
        2 | 2.0        | 4.03125    | 58.5       
        3 | 2.0        | 4.03125    | 1.953125   
        4 | 2.0        | 4.03125    | 1.953125   
        5 | 2.0        | 4.03125    | 1.2900390625
        6 | 2.0        | 4.03125    | 1.2900390625
        7 | 2.0        | 4.03125    | 1.13043212891
        8 | 2.0        | 4.03125    | 1.13043212891
        9 | 2.0        | 4.03125    | 1.06357192993
       10 | 2.0        | 4.03125    | 1.06357192993
       11 | 2.0        | 4.03125    | 1.03150010109
Generator output test:
([3, 5], 1604)
([2.5, 5.5], 58.5)
([2.0, 5.0], 58.5)
([2.25, 4.75], 1.953125)
([2.0, 4.5], 1.953125)
([2.125, 4.375], 1.2900390625)
([2.0, 4.25], 1.2900390625)
([2.0625, 4.1875], 1.13043212890625)
([2.0, 4.125], 1.13043212890625)
([2.03125, 4.09375], 1.0635719299316406)
([2.0, 4.0625], 1.0635719299316406)
([2.015625, 4.046875], 1.0315001010894775)

【问题讨论】:

  • "zip 我的patternSearch 生成器的结果与xrange" - 不喜欢enumerate
  • 我认为这是一种比if i &gt; imax: break更简单的终止方式@

标签: python debugging zip generator xrange


【解决方案1】:

您重用列表xmax 并更改它们的元素,但它始终是相同的列表,因此压缩列表由相同列表的12 倍组成。 生成器似乎可以工作,因为每个步骤都会打印列表。

换行

x = xmin

x = list(xmin)

【讨论】:

  • 除了生成器本身工作正常。查看输出。
  • @abatea:回答扩展
  • 好的,谢谢指点!我将收益线更改为yield(list(xmin),ymin),这解决了问题。所以以前,zip 中的每个项目都指向同一个列表对象。
  • 奇怪的是,zip 不应该只在调用时才评估,就像生成器一样?我的代码仍然应该在每次迭代时打印一次,而不是先评估整个列表,对吧?
  • @abatea 它取决于您使用的 Python 版本。在 Py 3 中 zip 是一个生成器,在 Py 2 中你需要依赖 itertools.izip 。由于您的代码中有 xrange,因此您使用的是 Py 2。
猜你喜欢
  • 2021-02-21
  • 1970-01-01
  • 2017-05-14
  • 2020-10-22
  • 2013-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多