天天看點

好程式員分享循環内的回調函數

  好程式員分享循環内的回調函數,問題出現在循環體内的回調函數,用一個很簡單的例子舉例:

  for x in xrange(3):

1.

  print "requests begin:%s"%x

2.

  def callback(respon):

3.

  print x

4.

  print respon.body

5.

  client.fetch("http://httpbin.org/get?x=%s" % x, callback)

  此例子忽略了等待回調函數完成的wait實作(不實作這個會導緻作為單個檔案運作的時候,還沒獲得結果就退出了),在tornado.testing中的AsyncTestCase提供了相關功能

  httpbin.org/get這個位址的作用是傳回了請求的json對象,形如:

  {

  "args": {

  "x": "0"

  },

  "headers": {

  "Accept-Encoding": "gzip",

6.

  "Connection": "close",

7.

  "Host": "httpbin.org",

8.

  "X-Request-Id": "95df3c15-7ed0-4a6d-830d-fb9629e66515"

9.

10.

  "origin": "192.81.129.91",

11.

  "url": "http://httpbin.org/get?x=0"

12.

  }

  但實際上,由于回調函數特殊的特性:通路閉包内局部變量的目前值。易知,在第一個請求

  

http://httpbin.org/get?x=0

的url傳回時,循環早已結束,此時的x已經為2,是以實際上雖然httpbin.org傳回的json告訴我們,get參數裡的x為0,但閉包内通路到的x已經是2了

  解決方法我想了兩個,一個是利用回調函數構造時的變量空間,在構造函數時即産生這個參數,形如:

  client = AsyncHTTPClient(self.io_loop)

  def callback(respon,num=x):

  print x, num

  if num == 2:

  self.stop()

  client.fetch("http://httpbin.org/get?x=%s" % x, wrap(x))

  一種是再包一層閉包(這層閉包也可以放在for外面):

  def wrap(number):

  num = number

  return callback

  #wrap放在for外面:

13.

14.

15.

16.

17.

18.

19.

20.

21.

22.

  client.fetch("http://httpbin.org/get?x=%s" % x, wrap(x))

  思索了一下,閉包的記憶體占用問題應當是不可避免的?當循環體的每一項(x)是一個大記憶體對象時,記憶體占用等同于不用疊代器用清單進行循環,除了這兩種不知道還有沒有更優雅的解決方案。。