FAQ
Hi,

I'd like to simplify the following string formatting:

solo = 'Han Solo'
jabba = 'Jabba the Hutt'
print "{solo} was captured by {jabba}".format(solo=solo, jabba=jabba)
# Han Solo was captured by Jabba the Hutt

What I don't like here is this: "solo=solo, jabba=jabba", i.e. the
same thing is repeated. In "solo=solo", the left part is a key and the
right part is the value of a local variable, but it looks strange.

I'd like something like this:
print "{solo} was captured by {jabba}".format(locals()) # WRONG!

But it doesn't work.

Do you have any idea?

Thanks,

Laszlo

Search Discussions

  • Chris Rebert at Jun 6, 2011 at 4:21 pm

    On Mon, Jun 6, 2011 at 9:15 AM, Jabba Laci wrote:
    Hi,

    I'd like to simplify the following string formatting:

    solo = 'Han Solo'
    jabba = 'Jabba the Hutt'
    print "{solo} was captured by {jabba}".format(solo=solo, jabba=jabba)
    # Han Solo was captured by Jabba the Hutt

    What I don't like here is this: "solo=solo, jabba=jabba", i.e. the
    same thing is repeated. In "solo=solo", the left part is a key and the
    right part is the value of a local variable, but it looks strange.

    I'd like something like this:
    print "{solo} was captured by {jabba}".format(locals()) ? ? ? ?# WRONG!

    But it doesn't work.

    Do you have any idea?
    print "{solo} was captured by {jabba}".format(**locals()) # RIGHT

    You must use prefix-** in the call to unpack the mapping as keyword arguments.
    Note that using locals() like this isn't best-practice.

    Cheers,
    Chris
  • Steve Crook at Jun 6, 2011 at 6:30 pm
    On Mon, 6 Jun 2011 12:15:35 -0400, Jabba Laci wrote in
    Message-Id: <mailman.2490.1307376958.9059.python-list at python.org>:
    solo = 'Han Solo'
    jabba = 'Jabba the Hutt'
    print "{solo} was captured by {jabba}".format(solo=solo, jabba=jabba)
    # Han Solo was captured by Jabba the Hutt
    How about:-

    print "%s was captured by %s" % (solo, jabba)
  • Ethan Furman at Jun 6, 2011 at 6:57 pm

    Steve Crook wrote:
    On Mon, 6 Jun 2011 12:15:35 -0400, Jabba Laci wrote in
    Message-Id: <mailman.2490.1307376958.9059.python-list at python.org>:
    solo = 'Han Solo'
    jabba = 'Jabba the Hutt'
    print "{solo} was captured by {jabba}".format(solo=solo, jabba=jabba)
    # Han Solo was captured by Jabba the Hutt
    How about:-

    print "%s was captured by %s" % (solo, jabba)
    Or even

    print "{} was captured by {}".format(solo, jabba)

    or how about

    print "{victim} was captured by {captor}".format(
    victim=solo, captor=jabba)

    or maybe

    print "{hapless_twit} was captured by {mega_bad_dude}".format(
    hapless_twit=solo, mega_bad_dude=jabba)


    ~Ethan~
  • Prasad, Ramit at Jun 6, 2011 at 8:21 pm
    print "{} was captured by {}".format(solo, jabba)
    Is this Python2.7 specific?

    Python 2.6.x :
    print "{} was captured by {}".format('t1', 't2')
    ValueError: zero length field name in format


    Ramit




    This communication is for informational purposes only. It is not
    intended as an offer or solicitation for the purchase or sale of
    any financial instrument or as an official confirmation of any
    transaction. All market prices, data and other information are not
    warranted as to completeness or accuracy and are subject to change
    without notice. Any comments or statements made herein do not
    necessarily reflect those of JPMorgan Chase & Co., its subsidiaries
    and affiliates.

    This transmission may contain information that is privileged,
    confidential, legally privileged, and/or exempt from disclosure
    under applicable law. If you are not the intended recipient, you
    are hereby notified that any disclosure, copying, distribution, or
    use of the information contained herein (including any reliance
    thereon) is STRICTLY PROHIBITED. Although this transmission and any
    attachments are believed to be free of any virus or other defect
    that might affect any computer system into which it is received and
    opened, it is the responsibility of the recipient to ensure that it
    is virus free and no responsibility is accepted by JPMorgan Chase &
    Co., its subsidiaries and affiliates, as applicable, for any loss
    or damage arising in any way from its use. If you received this
    transmission in error, please immediately contact the sender and
    destroy the material in its entirety, whether in electronic or hard
    copy format. Thank you.

    Please refer to http://www.jpmorgan.com/pages/disclosures for
    disclosures relating to European legal entities.
  • Ethan Furman at Jun 6, 2011 at 9:07 pm

    Prasad, Ramit wrote:
    print "{} was captured by {}".format(solo, jabba)
    Is this Python2.7 specific?

    Python 2.6.x :
    print "{} was captured by {}".format('t1', 't2')
    ValueError: zero length field name in format
    Apparently it is 2.7 and greater -- my apologies for not specifying that.

    ~Ethan~
  • Eric Snow at Jun 6, 2011 at 8:22 pm

    On Mon, Jun 6, 2011 at 10:15 AM, Jabba Laci wrote:
    Hi,

    I'd like to simplify the following string formatting:

    solo = 'Han Solo'
    jabba = 'Jabba the Hutt'
    print "{solo} was captured by {jabba}".format(solo=solo, jabba=jabba)
    # Han Solo was captured by Jabba the Hutt

    What I don't like here is this: "solo=solo, jabba=jabba", i.e. the
    same thing is repeated. In "solo=solo", the left part is a key and the
    right part is the value of a local variable, but it looks strange.

    I'd like something like this:
    print "{solo} was captured by {jabba}".format(locals()) ? ? ? ?# WRONG!

    But it doesn't work.

    Do you have any idea?
    You were close:

    print "{solo} was captured by {jabba}".format(**locals())

    This will turn locals() into keyword args for the format call. The
    tutorial has a good explanation on argument unpacking [1].

    -eric

    [1] http://docs.python.org/dev/tutorial/controlflow.html#unpacking-argument-lists
  • Ben Finney at Jun 7, 2011 at 12:11 am

    Chris Rebert <clp2 at rebertia.com> writes:

    print "{solo} was captured by {jabba}".format(**locals()) # RIGHT
    I tend to use ?u"foo {bar} baz".format(**vars())?, since ?vars? can also
    take the namespace of an object. I only need to remember one ?give me
    the namespace? function for formatting.
    You must use prefix-** in the call to unpack the mapping as keyword
    arguments. Note that using locals() like this isn't best-practice.
    Who says so, and do you find their argument convincing? Do you have a
    reference for that so we can see why?

    --
    \ ?If you write the word ?monkey? a million times, do you start |
    `\ to think you're Shakespeare?? ?Steven Wright |
    _o__) |
    Ben Finney
  • Ian Kelly at Jun 7, 2011 at 12:31 am

    On Mon, Jun 6, 2011 at 6:11 PM, Ben Finney wrote:
    You must use prefix-** in the call to unpack the mapping as keyword
    arguments. Note that using locals() like this isn't best-practice.
    Who says so, and do you find their argument convincing? Do you have a
    reference for that so we can see why?
    http://stackoverflow.com/questions/1550479/python-is-using-vars-locals-a-good-practice
  • Ian Kelly at Jun 7, 2011 at 12:38 am

    On Mon, Jun 6, 2011 at 6:11 PM, Ben Finney wrote:
    Chris Rebert <clp2 at rebertia.com> writes:
    print "{solo} was captured by {jabba}".format(**locals()) # RIGHT
    I tend to use ?u"foo {bar} baz".format(**vars())?, since ?vars? can also
    take the namespace of an object. I only need to remember one ?give me
    the namespace? function for formatting.
    If you're using an object namespace, then you can just do this:

    print("{o.solo} was captured by {o.jabba}".format(o=self))

    That looks a lot cleaner to me than passing in **vars(self). For
    locals(), I can see the appeal, but I tend to avoid it because it has
    the same icky feeling as doing an import *.

    Cheers,
    Ian
  • Steven D'Aprano at Jun 7, 2011 at 3:57 am

    On Tue, 07 Jun 2011 10:11:01 +1000, Ben Finney wrote:

    Chris Rebert <clp2 at rebertia.com> writes:
    print "{solo} was captured by {jabba}".format(**locals()) # RIGHT
    I tend to use ?u"foo {bar} baz".format(**vars())?, since ?vars? can also
    take the namespace of an object. I only need to remember one ?give me
    the namespace? function for formatting.
    You must use prefix-** in the call to unpack the mapping as keyword
    arguments. Note that using locals() like this isn't best-practice.
    Who says so, and do you find their argument convincing? Do you have a
    reference for that so we can see why?
    It's a code smell. Why is this code messing with locals() instead of
    using names explicitly? Is it possible that this code will attempt to
    modify locals()? I need to look twice to be sure its safe. Why do you
    need to pass *all* of the locals if only two names are used?

    Seeing an arbitrary large number of arguments passed to a piece of code
    that only requires two makes me feel hinky. It's not that it's
    *necessarily* bad, in and of itself, but it should make you take a
    second, closer look at it.

    Where possible, I'd rather be explicit about which names I want:

    solo = "Han Solo"
    jabba = "Jabba the Hutt"

    "{hero} was captured by {villain}.".format(hero=solo, villain=jabba)


    It also strikes me as potentially wasteful to unpack an arbitrarily large
    dict into keyword arguments, and then (presumably) have the format method
    pack them back into a dict again. Again, this might be trivial... but it
    might not be. No way of knowing just by reading that line of code, hence
    a code smell.


    Oh, and there's even a failure mode for this **locals() or **vars()
    pattern, at least for CPython. If you do this in production code, I hate
    you, but it can happen:

    globals()[42] = "spam spam spam" # Ouch!
    vars()
    {'__builtins__': <module '__builtin__' (built-in)>, '__name__':
    '__main__', 42: 'spam spam spam', '__doc__': None, '__package__': None}
    def f(**kwargs):
    ... print kwargs
    ...
    f(**vars())
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: f() keywords must be strings




    --
    Steven
  • Ben Finney at Jun 7, 2011 at 7:47 am

    Steven D'Aprano <steve+comp.lang.python at pearwood.info> writes:
    On Tue, 07 Jun 2011 10:11:01 +1000, Ben Finney wrote:

    I tend to use ?u"foo {bar} baz".format(**vars())?, since ?vars? can
    also take the namespace of an object. I only need to remember one
    ?give me the namespace? function for formatting.
    [?]
    It's a code smell. Why is this code messing with locals() instead of
    using names explicitly? Is it possible that this code will attempt to
    modify locals()? I need to look twice to be sure its safe. Why do you
    need to pass *all* of the locals if only two names are used?
    The names are explicit; they're in the format string. It's because I
    don't want to repeat the names several times that I'm making use of the
    dictionary provided by ?vars()?.
    Where possible, I'd rather be explicit about which names I want:

    solo = "Han Solo"
    jabba = "Jabba the Hutt"

    "{hero} was captured by {villain}.".format(hero=solo, villain=jabba)
    See, repeating those name references makes *me* hinky. I used those
    names because they refer to things I've already named.

    --
    \ ?The difference between religions and cults is determined by |
    `\ how much real estate is owned.? ?Frank Zappa |
    _o__) |
    Ben Finney

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedJun 6, '11 at 4:15p
activeJun 7, '11 at 7:47a
posts12
users9
websitepython.org

People

Translate

site design / logo © 2022 Grokbase