简体   繁体   中英

Genshi and Python Generators (yield)

How do I create/call a python generator in Genshi? Is that even possible?

For example, (and no i'm not looking for an alternate solution to this problem, of which there are many, including enumerate on the for each, etc):

 <?python
  """ a bunch of other code ... """
  def bg_color_gen():
    """ Alternate background color every call """
    while 1:
      yield "#FFFFFF"
      yield "#EBEBEB"
  ?>

And then calling this function:

  <fo:block background-color="${bg_color_gen()}">First entry</fo:block>
  <fo:block background-color="${bg_color_gen()}">Second entry</fo:block>
  <fo:block background-color="${bg_color_gen()}">Third entry</fo:block>

This has nothing to do with my < fo:block >, which you could replace with < div >. It is not an FO question but a Genshi question. I'm guessing Genshi doesn't recognize the 'yield' and runs 'while 1' ad-infinitum?

Also, I do realize I could use a global to keep track of a counter, and then call

 counter++
 if counter%yieldCount==0: return "#FFFFFFF"
 elif counter%yieldCount==1: return "#EBEBEB"

But this is not a generator and gets ugly very quickly!

Clarification: Another way to ask this question: how would you code

def fib():
    a,b = 0,1
    while True:
        yield a
        b = a+b
        yield b
        a = a+b

Which would then be called in the sentence "The first number is $fib(), the second is $fib(), the third is $fib(), and so on."

================================================

Updated full solution based on accepted answer:

<?python
def fib_generator():
    a,b = 0,1
    while True:
        yield a
        b = a+b
        yield b
        a = a+b
fib = fib_generator()
?>


The first number is ${next(fib)}, 
the second is ${next(fib)},
the third is ${next(fib)}, and so on.

Without knowing the structure of your content, I would suggest the following:

<fo:block py:for="i, entry in entries"
          background-color="${'#FFFFFF' if i % 2 else '#EBEBEB'}">
  ${entry}
</fo:block>

However if you truly want to use a generator then you could just evaluate using Python's native next()

<py:with vars="color=bg_color_gen();">
  <fo:block background-color="${next(color)}">
</py:with>

You would want to declare the generator first and then call next on it to get a yield ed color.

In this case you are passing three different instances of the generator created by calling bg_color_gen() ie)

# this creates a generator
>>> bg_color_gen()
<generator object bg_color_gen at 0x02B21A30>
>>> bgcg = bg_color_gen()
# this gets values
>>> next(bgcg)
'#FFFFFF'
>>> next(bgcg)
'#EBEBEB'
>>> next(bgcg)
'#FFFFFF'
>>> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM