using generators with format strings

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

    #1

    using generators with format strings

    I have a weird request.

    I want to be able to say

    def myvalues():
    while True:
    # stuff that determines a new somevalue
    yield somevalue

    x = "Hello, %s, this is a %s with %s and %s on top of %s" % myvalues()
    y = "Yes it's true that %s has way too many %s's" % myvalues()

    I was hoping that myvalues() would be iterated over, but instead the
    interpreter gives me a "TypeError: not enough arguments for format string"
    error. I tried tuple(myvalues( )) and I think that kinda works but of
    course myvalues goes into an infinite loop. myvalues will not know before
    hand how many times it will be called.

    Is there actually a simple way of doing this that I'm overlooking?



    ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
    http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
    ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
  • Calvin Spealman

    #2
    Re: using generators with format strings

    The generators are not list-type objects, but iterators. Because the %
    operator does not operate on iterators directly (because, presumably, you
    may be wanting to print the iterator itself, not the items it iterates
    over), you must construct a list out of it, which can be done very easily,
    as you can see.

    x = "Hello, %s, this is a %s with %s and %s on top of %s" % [ i for i in
    myvalues()]
    y = "Yes it's true that %s has way too many %s's" % [i for i in myvalues()]

    marduk wrote:
    [color=blue]
    > I have a weird request.
    >
    > I want to be able to say
    >
    > def myvalues():
    > while True:
    > # stuff that determines a new somevalue
    > yield somevalue
    >
    > x = "Hello, %s, this is a %s with %s and %s on top of %s" % myvalues()
    > y = "Yes it's true that %s has way too many %s's" % myvalues()
    >
    > I was hoping that myvalues() would be iterated over, but instead the
    > interpreter gives me a "TypeError: not enough arguments for format string"
    > error. I tried tuple(myvalues( )) and I think that kinda works but of
    > course myvalues goes into an infinite loop. myvalues will not know before
    > hand how many times it will be called.
    >
    > Is there actually a simple way of doing this that I'm overlooking?
    >
    >
    >
    > ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet
    > News==---- http://www.newsfeed.com The #1 Newsgroup Service in the World![color=green]
    > >100,000 Newsgroups ---= 19 East/West-Coast Specialized Servers - Total[/color]
    > Privacy via Encryption =---[/color]

    --


    Comment

    • Terry Reedy

      #3
      Re: using generators with format strings


      "Calvin Spealman" <calvin@ironfro ggy.com> wrote in message
      news:1177931.tn jPut6V3j@ironfr oggy.com...[color=blue]
      > The generators are not list-type objects, but iterators. Because the %
      > operator does not operate on iterators directly (because, presumably, you
      > may be wanting to print the iterator itself, not the items it iterates
      > over), you must construct a list out of it, which can be done very[/color]
      easily,[color=blue]
      > as you can see.
      >
      > x = "Hello, %s, this is a %s with %s and %s on top of %s" % [ i for i in
      > myvalues()]
      > y = "Yes it's true that %s has way too many %s's" % [i for i in[/color]
      myvalues()]

      list(myvalues() ) is even more concise and more direct than the list comp

      tjr



      Comment

      • Christopher T King

        #4
        Re: using generators with format strings

        On Mon, 26 Jul 2004, Calvin Spealman wrote:
        [color=blue]
        > The generators are not list-type objects, but iterators. Because the %
        > operator does not operate on iterators directly (because, presumably, you
        > may be wanting to print the iterator itself, not the items it iterates
        > over), you must construct a list out of it, which can be done very easily,
        > as you can see.[/color]

        Not quite, because for the same reason as generators, lists are passed to
        % as a single argument. The arguments must be contained in a tuple
        (tuple(myvalues ()) does nicely).

        Comment

        • John Lenton

          #5
          Re: using generators with format strings

          On Tue, 27 Jul 2004 09:15:57 -0400, Christopher T King <squirrel@wpi.e du> wrote:[color=blue]
          > On Mon, 26 Jul 2004, Calvin Spealman wrote:
          >[color=green]
          > > The generators are not list-type objects, but iterators. Because the %
          > > operator does not operate on iterators directly (because, presumably, you
          > > may be wanting to print the iterator itself, not the items it iterates
          > > over), you must construct a list out of it, which can be done very easily,
          > > as you can see.[/color]
          >
          > Not quite, because for the same reason as generators, lists are passed to
          > % as a single argument. The arguments must be contained in a tuple
          > (tuple(myvalues ()) does nicely).[/color]

          does anyone else get the feeling that (str %) should have a third
          behaviour wrt generators? By this I mean that str % seq is one
          behaviour, str % dict is another, and there should be a str % iter,
          probably consuming items from the iterator up to the number of
          arguments of the format string?

          --
          John Lenton (jlenton@gmail. com) -- Random fortune:
          bash: fortune: command not found

          Comment

          • Christopher T King

            #6
            Re: using generators with format strings

            On Tue, 27 Jul 2004, John Lenton wrote:
            [color=blue]
            > does anyone else get the feeling that (str %) should have a third
            > behaviour wrt generators? By this I mean that str % seq is one
            > behaviour, str % dict is another, and there should be a str % iter,
            > probably consuming items from the iterator up to the number of
            > arguments of the format string?[/color]

            The only argument I see against this is that it could break existing code
            of the form '%r' % some_object, where some_object could easily be an
            iterable object (say, a numarray array). Of course, limiting it to only
            generators rather than iterators in general would fix this, but then the
            benefit gained seems too small to justify the cost of implementing another
            exception to the rule.

            Comment

            • Bengt Richter

              #7
              Re: using generators with format strings

              On Wed, 21 Jul 2004 15:21:50 -0500, marduk <marduk@python. net> wrote:
              [color=blue]
              >I have a weird request.
              >
              >I want to be able to say
              >
              >def myvalues():
              > while True:
              > # stuff that determines a new somevalue
              > yield somevalue
              >
              >x = "Hello, %s, this is a %s with %s and %s on top of %s" % myvalues()
              >y = "Yes it's true that %s has way too many %s's" % myvalues()
              >
              >I was hoping that myvalues() would be iterated over, but instead the
              >interpreter gives me a "TypeError: not enough arguments for format string"
              >error. I tried tuple(myvalues( )) and I think that kinda works but of
              >course myvalues goes into an infinite loop. myvalues will not know before
              >hand how many times it will be called.
              >
              >Is there actually a simple way of doing this that I'm overlooking?
              >[/color]

              If you are willing to modify your format strings so they call on a
              mapping (with ignored key '' in this case), you can supply a mapping that will do the job:
              [color=blue][color=green][color=darkred]
              >>> def myvalues():[/color][/color][/color]
              ... values = 'one two three'.split() + [4,5,6]
              ... while True:
              ... # stuff that determines somevalue
              ... for somevalue in values:
              ... yield somevalue
              ...[color=blue][color=green][color=darkred]
              >>> mapping = type('',(),{'__ getitem__':lamb da s,k,g=myvalues( ).next:g()})()
              >>> x = "Hello, %s, this is a %s with %s and %s on top of %s".replace('%' ,'%()') % mapping
              >>> y = "Yes it's true that %s has way too many %s's".replace(' %','%()') % mapping
              >>> x[/color][/color][/color]
              'Hello, one, this is a two with three and 4 on top of 5'[color=blue][color=green][color=darkred]
              >>> y[/color][/color][/color]
              "Yes it's true that 6 has way too many one's"

              You can obviously define mapping as an instance of a more conventionally defined class also,
              and pass the generator to its constructor. Maybe even differentiate among multiple keyword-named
              generators if you want to feed in several value streams and not ignore keys from the format.

              You don't want to use .replace('%','% ()') if your format string already has some '%(...) or
              '%%' instances in it, of course.

              Hm, maybe if '%s' without mapping names were interpreted as a mapping with an integer key
              whose value was the position of the %s in the format, then a mapping could (if it had the
              integer key in question, otherwise its __str__ method would be called) be used with ordinary
              formats as well. E.g.,

              '%s %04x' % mapping

              would get mapping[0] and mapping[1] as the values to convert per the format. Note that
              that's not equivalent to '%(0)s %(1)04x' which would use keys '0' and '1' instead of 0 and 1.
              You could of course make a mapping that would ignore the keys for some purpose, as I did above.
              Just a wild idea, don't take too seriously ;-)

              Regards,
              Bengt Richter

              Comment

              • Bengt Richter

                #8
                Re: using generators with format strings

                On Tue, 27 Jul 2004 11:28:29 -0400, Christopher T King <squirrel@WPI.E DU> wrote:
                [color=blue]
                >On Tue, 27 Jul 2004, John Lenton wrote:
                >[color=green]
                >> does anyone else get the feeling that (str %) should have a third
                >> behaviour wrt generators? By this I mean that str % seq is one
                >> behaviour, str % dict is another, and there should be a str % iter,
                >> probably consuming items from the iterator up to the number of
                >> arguments of the format string?[/color]
                >
                >The only argument I see against this is that it could break existing code
                >of the form '%r' % some_object, where some_object could easily be an
                >iterable object (say, a numarray array). Of course, limiting it to only
                >generators rather than iterators in general would fix this, but then the
                >benefit gained seems too small to justify the cost of implementing another
                >exception to the rule.
                >[/color]

                You could subtype str and override __mod__ to do it (which I'll leave
                as an exercise ;-) e.g.,

                class MYFMT(str):
                def __mod__(self, args):
                ...

                and then use it like

                MYFMT('formatte d string args from generator: %s %r %(mapping_key)s ') % generator

                Then you could make it do anything you like without changing current python, even
                mixing in mapping usage if you wanted to.

                Regards,
                Bengt Richter

                Comment

                Working...