Generators can only yield ints?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • defn noob

    Generators can only yield ints?

    def letters():
    a = xrange(ord('a') , ord('z')+1)
    B = xrange(ord('A') , ord('Z')+1)
    while True:
    yield chr(a)
    yield chr(B)

    >>l = letters()
    >>l.next()
    Traceback (most recent call last):
    File "<pyshell#225>" , line 1, in <module>
    l.next()
    File "<pyshell#223>" , line 5, in letters
    yield chr(a)
    TypeError: an integer is required
    >>>

    Any way to get around this?
  • bearophileHUGS@lycos.com

    #2
    Re: Generators can only yield ints?

    defn noob:
    Any way to get around this?
    Your code is wrong, this is one of the correct versions:

    from itertools import izip

    def letters():
    lower = xrange(ord('a') , ord('z')+1)
    upper = xrange(ord('A') , ord('Z')+1)
    for lc, uc in izip(lower, upper):
    yield chr(lc)
    yield chr(uc)

    print list(letters())

    There are other ways to do the same thing.

    Bye,
    bearophile

    Comment

    • Medardo Rodriguez (Merchise Group)

      #3
      Re: Generators can only yield ints?

      On Fri, Aug 22, 2008 at 6:44 PM, defn noob <circularfunc@y ahoo.sewrote:
      def letters():
      a = xrange(ord('a') , ord('z')+1)
      B = xrange(ord('A') , ord('Z')+1)
      while True:
      yield chr(a)
      yield chr(B)
      >
      >
      TypeError: an integer is required
      No. The problem is that "chr function" receives "int"
      "a" and "B" are generators of "int" items.

      What exactly you intent with that code?

      Maybe:
      #<code>
      def letters():
      for i in xrange(ord('a') , ord('z')+1):
      yield chr(i)
      for i in xrange(ord('A') , ord('Z')+1):
      yield chr(i)

      for letter in letters():
      print letter
      #</code>

      Regards

      Comment

      • Wojtek Walczak

        #4
        Re: Generators can only yield ints?

        On Fri, 22 Aug 2008 15:44:15 -0700 (PDT), defn noob wrote:
        def letters():
        a = xrange(ord('a') , ord('z')+1)
        B = xrange(ord('A') , ord('Z')+1)
        while True:
        yield chr(a)
        yield chr(B)
        >
        >
        >>>l = letters()
        >>>l.next()
        >
        Traceback (most recent call last):
        File "<pyshell#225>" , line 1, in <module>
        l.next()
        File "<pyshell#223>" , line 5, in letters
        yield chr(a)
        TypeError: an integer is required
        >>>>
        The error you're seeing is a result of passing
        non-integer to chr() function, it has nothing to do
        with generators:
        >>chr([])
        Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        TypeError: an integer is required
        >>>
        I have simplified your code a bit:
        -------------
        import string
        def letters():
        a, B = (string.letters ,) * 2
        for i in zip(a, B):
        yield i[0]
        yield i[1]

        l = letters()

        print l.next()
        print l.next()
        print l.next()
        --------------

        and the output:

        $ python genlet.py
        a
        a
        b
        $

        Is that what you tried to achieve?

        --
        Regards,
        Wojtek Walczak,

        Comment

        • Steven D'Aprano

          #5
          Re: Generators can only yield ints?

          On Fri, 22 Aug 2008 15:44:15 -0700, defn noob wrote:
          def letters():
          a = xrange(ord('a') , ord('z')+1)
          B = xrange(ord('A') , ord('Z')+1)
          while True:
          yield chr(a)
          yield chr(B)
          >
          >
          >>>l = letters()
          >>>l.next()
          >
          Traceback (most recent call last):
          File "<pyshell#225>" , line 1, in <module>
          l.next()
          File "<pyshell#223>" , line 5, in letters
          yield chr(a)
          TypeError: an integer is required
          >>>>
          >>>>
          >
          Any way to get around this?
          Yes, write code that isn't buggy :)

          Generators can return anything you want. Your problem is that you're
          passing an xrange object to chr() instead of an int. Try this:

          def letters():
          a = xrange(ord('a') , ord('z')+1)
          B = xrange(ord('A') , ord('Z')+1)
          for t in zip(a, B):
          yield chr(t[0])
          yield chr(t[1])

          But (arguably) a better way is:

          def letters():
          from string import ascii_letters as letters
          for a,b in zip(letters[0:26], letters[26:]):
          yield a
          yield b


          Note that it is important to use ascii_letters rather than letters,
          because in some locales the number of uppercase and lowercase letters
          differ.


          --
          Steven

          Comment

          • Lie

            #6
            Re: Generators can only yield ints?

            On Aug 23, 5:44 am, defn noob <circularf...@y ahoo.sewrote:
            def letters():
                    a = xrange(ord('a') , ord('z')+1)
                    B = xrange(ord('A') , ord('Z')+1)
                    while True:
                            yield chr(a)
                            yield chr(B)
            >
            >l = letters()
            >l.next()
            >
            Traceback (most recent call last):
              File "<pyshell#225>" , line 1, in <module>
                l.next()
              File "<pyshell#223>" , line 5, in letters
                yield chr(a)
            TypeError: an integer is required
            >
            >
            >
            Any way to get around this?
            The most direct translation on what you've done, with corrections, is
            either this:

            def letters():
            a = xrange(ord('a') , ord('z') + 1)
            B = xrange(ord('A') , ord('Z') + 1)
            while True:
            yield a
            yield B
            >>l = letters()
            >>l.next()
            xrange(97, 123)

            or this:

            def letters():
            a = xrange(ord('a') , ord('z') + 1)
            B = xrange(ord('A') , ord('Z') + 1)
            while True:
            yield [chr(char) for char in a]
            yield [chr(char) for char in B]
            >>l = letters()
            >>l.next()
            ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
            'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

            but my psychic ability guessed that you actually wanted this instead:


            def letters():
            a = xrange(ord('a') , ord('z') + 1)
            B = xrange(ord('A') , ord('Z') + 1)
            a = [chr(char) for char in a]
            B = [chr(char) for char in B]
            index = 0
            while index < 26:
            yield a[index]
            yield B[index]
            index += 1
            >>l = letters()
            >>l.next()
            'a'

            or possibly in a more pythonic style, using for:

            def letters():
            a = xrange(ord('a') , ord('z') + 1)
            B = xrange(ord('A') , ord('Z') + 1)
            for lower, upper in zip(a, B):
            yield chr(lower)
            yield chr(upper)
            >>l = letters()
            >>l.next()
            'a'

            paralelly, my psychic ability also tells me that you might prefer this
            instead:

            def letters():
            a = xrange(ord('a') , ord('z') + 1)
            B = xrange(ord('A') , ord('Z') + 1)
            for lower, upper in zip(a, B):
            yield chr(lower), chr(upper)
            >>l = letters()
            >>l.next()
            ('a', 'A')

            Comment

            Working...