using generators with format strings

Discussion in 'Python' started by marduk, Jul 21, 2004.

  1. marduk

    marduk Guest

    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 =---
     
    marduk, Jul 21, 2004
    #1
    1. Advertising

  2. 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:

    > 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, Jul 26, 2004
    #2
    1. Advertising

  3. marduk

    Terry Reedy Guest

    "Calvin Spealman" <> wrote in message
    news:...
    > 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()]

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

    tjr
     
    Terry Reedy, Jul 27, 2004
    #3
  4. On Mon, 26 Jul 2004, Calvin Spealman wrote:

    > 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.


    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).
     
    Christopher T King, Jul 27, 2004
    #4
  5. marduk

    John Lenton Guest

    On Tue, 27 Jul 2004 09:15:57 -0400, Christopher T King <> wrote:
    > On Mon, 26 Jul 2004, Calvin Spealman wrote:
    >
    > > 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.

    >
    > 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).


    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 () -- Random fortune:
    bash: fortune: command not found
     
    John Lenton, Jul 27, 2004
    #5
  6. On Tue, 27 Jul 2004, John Lenton wrote:

    > 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?


    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.
     
    Christopher T King, Jul 27, 2004
    #6
  7. On Wed, 21 Jul 2004 15:21:50 -0500, marduk <> wrote:

    >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?
    >


    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:

    >>> def myvalues():

    ... values = 'one two three'.split() + [4,5,6]
    ... while True:
    ... # stuff that determines somevalue
    ... for somevalue in values:
    ... yield somevalue
    ...
    >>> mapping = type('',(),{'__getitem__':lambda 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

    'Hello, one, this is a two with three and 4 on top of 5'
    >>> y

    "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
     
    Bengt Richter, Jul 27, 2004
    #7
  8. On Tue, 27 Jul 2004 11:28:29 -0400, Christopher T King <> wrote:

    >On Tue, 27 Jul 2004, John Lenton wrote:
    >
    >> 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?

    >
    >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.
    >


    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('formatted 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
     
    Bengt Richter, Jul 27, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Francis Avila
    Replies:
    0
    Views:
    478
    Francis Avila
    Nov 2, 2003
  2. The_Incubator
    Replies:
    4
    Views:
    437
    Linus Elman
    Jan 6, 2004
  3. fishboy
    Replies:
    0
    Views:
    373
    fishboy
    May 31, 2004
  4. Guest
    Replies:
    3
    Views:
    292
    Peter Otten
    Jul 22, 2004
  5. Ben

    Strings, Strings and Damned Strings

    Ben, Jun 22, 2006, in forum: C Programming
    Replies:
    14
    Views:
    787
    Malcolm
    Jun 24, 2006
Loading...

Share This Page