The Yield statement

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Alex Bryan

    The Yield statement

    Okay, so i don't really understand the Yield thing and i know it is
    useful. I've read a few things about it but it is all programming
    jargon and so basically it is hard for me to understand. So can anyone
    give me a description or link me to a site that has a good definition
    and/or examples of it? If you could I would really appreciate it.
  • Larry Bates

    #2
    Re: The Yield statement

    Alex Bryan wrote:
    Okay, so i don't really understand the Yield thing and i know it is
    useful. I've read a few things about it but it is all programming jargon
    and so basically it is hard for me to understand. So can anyone give me
    a description or link me to a site that has a good definition and/or
    examples of it? If you could I would really appreciate it.
    Use yield when you want the function to act as a generator. That is each time
    it is called it generates a response and returns it, but leaves its state intact
    so that the next time you call it, it can pick up where it left off and continue on.

    Best example I ever saw is the code that implements os.walk() function:

    def walk(top, topdown=True, onerror=None):
    """
    Example:

    from os.path import join, getsize
    for root, dirs, files in walk('python/Lib/email'):
    print root, "consumes",
    print sum([getsize(join(ro ot, name)) for name in files]),
    print "bytes in", len(files), "non-directory files"
    if 'CVS' in dirs:
    dirs.remove('CV S') # don't visit CVS directories
    """

    from os.path import join, isdir, islink

    try:
    names = listdir(top)
    except error, err:
    if onerror is not None:
    onerror(err)
    return

    dirs, nondirs = [], []
    for name in names:
    if isdir(join(top, name)):
    dirs.append(nam e)
    else:
    nondirs.append( name)

    if topdown:
    yield top, dirs, nondirs
    for name in dirs:
    path = join(top, name)
    if not islink(path):
    for x in walk(path, topdown, onerror):
    yield x
    if not topdown:
    yield top, dirs, nondirs


    Actually this code uses yield and is recursive. Pretty neat.

    -Larry

    Comment

    • Mensanator

      #3
      Re: The Yield statement

      On Jun 30, 5:31 pm, Alex Bryan <alexnbr...@gma il.comwrote:
      Okay, so i don't really understand the Yield thing and i know it is  
      useful. I've read a few things about it but it is all programming  
      jargon and so basically it is hard for me to understand. So can anyone  
      give me a description or link me to a site that has a good definition  
      and/or examples of it? If you could I would really appreciate it.
      You know what a function does, right? If I were to say

      x = NextPrime(3)

      then x should be set to 5. The NextPrime function
      does this by evaluating the input argument (3) and
      doing

      return p

      as the last statement (p having been determined to be 5).

      Now, suppose you had a function Primes (i.e., a function
      that returns ALL the primes). Obviously, since there are
      an infinite number of them, the function would never
      end since it would eventually eat up all your memory
      trying to create a list with infinite elements.

      However, if Primes were a generator, you could have it
      return just 1 result at a time. The generator would
      keep track of the last prime issued so that every .next()
      call would give you the next prime in the sequence.

      That's what "yield" does. It functions like a return,
      only returning a single element of an iteration.
      For infinite loops, the program simply stops calling
      the function when it has enough (or tells the function
      to stop).

      Here's an example. Note that before it enters the output
      loop it does a couple things. First, it checks for valid
      input. If not valid, it executes a "return" statement
      which kills the generator.

      If valid, it issues a "yield" prior to the loop. It must
      do this to issue the first partition. The loop will issue
      all subsequent partitions with its "yield" statements.

      This particular generator is always a finite loop. Although
      the number of generated partitions can be quite large, best
      to test by doing C(depth-1,width-1) before asking for
      all the results (which is what "for i in p" does).

      def partition_gener ator(depth,widt h):
      """creates all partions of a given depth,widtth (depth>=width)
      depth objects in width bins such that each bin has at least 1 object
      this function is a generator (does comb(depth-1,width-1) partitions)

      partition_gener ator(depth,widt h)
      depth: total inverse rule 1 count (p of 2**p)
      width: total inverse rule 2 count (q of 3**q)
      sv: sequence vector (the partition)
      returns sequence vector [sv]
      """
      def move_col(c):
      sv[c-1] += 1
      sv[c] -= 1
      def find_c():
      i = -1
      while i<0:
      if sv[i]>1:
      return i
      i -= 1
      def rollover(c):
      move_col(c)
      sv[-1] = sv[c]
      sv[c] = 1
      if depth<width: # error
      print 'depth',depth,' must be >= to width',width
      return # kills generator
      max_element = depth - width + 1
      sv = [1 for i in range(width)]
      sv[-1] = max_element
      yield sv[:] # first partition
      while sv[0]<max_element: # rest are generated by this loop
      c = find_c()
      if c < -1:
      rollover(c)
      yield sv[:] # must yield copy of sv, not sv
      else:
      move_col(c)
      yield sv[:]

      p = partition_gener ator(6,4)

      for i in p: print i

      ## [1, 1, 1, 3]
      ## [1, 1, 2, 2]
      ## [1, 1, 3, 1]
      ## [1, 2, 1, 2]
      ## [1, 2, 2, 1]
      ## [1, 3, 1, 1]
      ## [2, 1, 1, 2]
      ## [2, 1, 2, 1]
      ## [2, 2, 1, 1]
      ## [3, 1, 1, 1]

      Comment

      • John Machin

        #4
        Re: The Yield statement

        On Jul 1, 8:31 am, Alex Bryan <alexnbr...@gma il.comwrote:
        Okay, so i don't really understand the Yield thing and i know it is
        useful. I've read a few things about it but it is all programming
        jargon and so basically it is hard for me to understand. So can anyone
        give me a description or link me to a site that has a good definition
        and/or examples of it? If you could I would really appreciate it.
        Try this:



        (ignore the "tricks" word in the title)

        Comment

        • inhahe

          #5
          Re: The Yield statement


          "Alex Bryan" <alexnbryan@gma il.comwrote in message
          news:mailman.10 09.1214865088.1 044.python-list@python.org ...
          Okay, so i don't really understand the Yield thing and i know it is
          useful. I've read a few things about it but it is all programming jargon
          and so basically it is hard for me to understand. So can anyone give me a
          description or link me to a site that has a good definition and/or
          examples of it? If you could I would really appreciate it.
          Really short answer:

          def f():
          yield 1
          yield 2
          yield 3

          for x in f(): print x,
          # should print 1 2 3

          def f():
          for x in xrange(10):
          yield x

          for x in f(): print x,
          # should print 0 1 2 3 4 5 6 7 8 9

          note that this won't work;
          def f():
          for x in xrange(10):
          for y in xrange(10):
          yield (x,y)

          yield just doesn't work right with multiple levels of loops. i had to
          discover that the hard way.



          Comment

          • Mark Tolonen

            #6
            Re: The Yield statement


            "inhahe" <inhahe@gmail.c omwrote in message
            news:z6_bk.2496 0$AJ6.1423@bign ews8.bellsouth. net...
            >
            "Alex Bryan" <alexnbryan@gma il.comwrote in message
            news:mailman.10 09.1214865088.1 044.python-list@python.org ...
            >Okay, so i don't really understand the Yield thing and i know it is
            >useful. I've read a few things about it but it is all programming jargon
            >and so basically it is hard for me to understand. So can anyone give me
            >a description or link me to a site that has a good definition and/or
            >examples of it? If you could I would really appreciate it.
            >
            Really short answer:
            >
            def f():
            yield 1
            yield 2
            yield 3
            >
            for x in f(): print x,
            # should print 1 2 3
            >
            def f():
            for x in xrange(10):
            yield x
            >
            for x in f(): print x,
            # should print 0 1 2 3 4 5 6 7 8 9
            >
            note that this won't work;
            def f():
            for x in xrange(10):
            for y in xrange(10):
            yield (x,y)
            >
            yield just doesn't work right with multiple levels of loops. i had to
            discover that the hard way.
            Huh? Works fine:
            >>def f():
            .... for x in xrange(10):
            .... for y in xrange(10):
            .... yield (x,y)
            ....
            >>for x in f(): print x,
            ....
            (0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9) (1, 0)
            (1,
            1) (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) (1, 7) (1, 8) (1, 9) (2, 0) (2, 1)
            (2, 2)
            (2, 3) (2, 4) (2, 5) (2, 6) (2, 7) (2, 8) (2, 9) (3, 0) (3, 1) (3, 2) (3,
            3) (3
            , 4) (3, 5) (3, 6) (3, 7) (3, 8) (3, 9) (4, 0) (4, 1) (4, 2) (4, 3) (4, 4)
            (4, 5
            ) (4, 6) (4, 7) (4, 8) (4, 9) (5, 0) (5, 1) (5, 2) (5, 3) (5, 4) (5, 5) (5,
            6) (
            5, 7) (5, 8) (5, 9) (6, 0) (6, 1) (6, 2) (6, 3) (6, 4) (6, 5) (6, 6) (6, 7)
            (6,
            8) (6, 9) (7, 0) (7, 1) (7, 2) (7, 3) (7, 4) (7, 5) (7, 6) (7, 7) (7, 8) (7,
            9)
            (8, 0) (8, 1) (8, 2) (8, 3) (8, 4) (8, 5) (8, 6) (8, 7) (8, 8) (8, 9) (9, 0)
            (9,
            1) (9, 2) (9, 3) (9, 4) (9, 5) (9, 6) (9, 7) (9, 8) (9, 9)

            -Mark

            Comment

            • Jorgen Grahn

              #7
              Re: The Yield statement

              On Sun, 6 Jul 2008 00:29:26 -0700, Mark Tolonen <M8R-yfto6h@mailinat or.comwrote:
              >
              "inhahe" <inhahe@gmail.c omwrote in message
              news:z6_bk.2496 0$AJ6.1423@bign ews8.bellsouth. net...
              ....
              >note that this won't work;
              >def f():
              > for x in xrange(10):
              > for y in xrange(10):
              > yield (x,y)
              >>
              >yield just doesn't work right with multiple levels of loops. i had to
              >discover that the hard way.
              >
              Huh? Works fine: [...]
              Yes -- as is expected. Yield would be much less useful if it only
              work with strange restrictions on the structure of the function
              containing it.

              As far as I can tell, you can pick any function, stick zero or more
              yield statements into it, and it will work as expected: hit a yield,
              and you get another value for your sequence.

              /Jorgen

              --
              // Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
              \X/ snipabacken.se R'lyeh wgah'nagl fhtagn!

              Comment

              • Paul Hankin

                #8
                Re: The Yield statement

                On Jul 1, 12:45 am, Mensanator <mensana...@aol .comwrote:
                Here's an example.
                ...
                def partition_gener ator(depth,widt h):
                  """creates all partions of a given depth,widtth (depth>=width)
                  depth objects in width bins such that each bin has at least 1 object
                  this function is a generator (does comb(depth-1,width-1) partitions)
                >
                  partition_gener ator(depth,widt h)
                  depth:  total inverse rule 1 count (p of 2**p)
                  width:  total inverse rule 2 count (q of 3**q)
                  sv:     sequence vector (the partition)
                  returns sequence vector [sv]
                  """
                  def move_col(c):
                    sv[c-1] += 1
                    sv[c] -= 1
                  def find_c():
                    i = -1
                    while i<0:
                      if sv[i]>1:
                        return i
                      i -= 1
                  def rollover(c):
                    move_col(c)
                    sv[-1] = sv[c]
                    sv[c] = 1
                  if depth<width:                # error
                    print 'depth',depth,' must be >= to width',width
                    return                       # kills generator
                  max_element = depth - width + 1
                  sv = [1 for i in range(width)]
                  sv[-1] = max_element
                  yield sv[:]                    # first partition
                  while sv[0]<max_element:       # rest are generated by this loop
                    c = find_c()
                    if c < -1:
                      rollover(c)
                      yield sv[:]   # must yield copy of sv, not sv
                    else:
                      move_col(c)
                      yield sv[:]
                It's just an example I know, but you can write this much more
                cleanly...

                def partitions(n, length):
                """Generate all sequences of positive numbers of the given
                length that sum to n."""
                assert 0 < length <= n
                if length == 1:
                yield [n]
                return
                for i in xrange(1, n + 2 - length):
                for p in partitions(n - i, length - 1):
                yield [i] + p

                --
                Paul Hankin

                Comment

                Working...