Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #7092 > unrolled thread

Re: new string formatting with local variables

Started byChris Rebert <clp2@rebertia.com>
First post2011-06-06 09:21 -0700
Last post2011-06-07 17:47 +1000
Articles 6 — 4 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: new string formatting with local variables Chris Rebert <clp2@rebertia.com> - 2011-06-06 09:21 -0700
    Re: new string formatting with local variables Ben Finney <ben+python@benfinney.id.au> - 2011-06-07 10:11 +1000
      Re: new string formatting with local variables Ian Kelly <ian.g.kelly@gmail.com> - 2011-06-06 18:31 -0600
      Re: new string formatting with local variables Ian Kelly <ian.g.kelly@gmail.com> - 2011-06-06 18:38 -0600
      Re: new string formatting with local variables Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-07 03:57 +0000
        Re: new string formatting with local variables Ben Finney <ben+python@benfinney.id.au> - 2011-06-07 17:47 +1000

#7092 — Re: new string formatting with local variables

FromChris Rebert <clp2@rebertia.com>
Date2011-06-06 09:21 -0700
SubjectRe: new string formatting with local variables
Message-ID<mailman.2491.1307377282.9059.python-list@python.org>
On Mon, Jun 6, 2011 at 9:15 AM, Jabba Laci <jabba.laci@gmail.com> 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
--
http://rebertia.com

[toc] | [next] | [standalone]


#7120

FromBen Finney <ben+python@benfinney.id.au>
Date2011-06-07 10:11 +1000
Message-ID<87zklu1ox6.fsf@benfinney.id.au>
In reply to#7092
Chris Rebert <clp2@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

[toc] | [prev] | [next] | [standalone]


#7121

FromIan Kelly <ian.g.kelly@gmail.com>
Date2011-06-06 18:31 -0600
Message-ID<mailman.2511.1307406733.9059.python-list@python.org>
In reply to#7120
On Mon, Jun 6, 2011 at 6:11 PM, Ben Finney <ben+python@benfinney.id.au> 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

[toc] | [prev] | [next] | [standalone]


#7122

FromIan Kelly <ian.g.kelly@gmail.com>
Date2011-06-06 18:38 -0600
Message-ID<mailman.2512.1307407121.9059.python-list@python.org>
In reply to#7120
On Mon, Jun 6, 2011 at 6:11 PM, Ben Finney <ben+python@benfinney.id.au> wrote:
> Chris Rebert <clp2@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

[toc] | [prev] | [next] | [standalone]


#7132

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-06-07 03:57 +0000
Message-ID<4deda1c6$0$29980$c3e8da3$5496439d@news.astraweb.com>
In reply to#7120
On Tue, 07 Jun 2011 10:11:01 +1000, Ben Finney wrote:

> Chris Rebert <clp2@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

[toc] | [prev] | [next] | [standalone]


#7142

FromBen Finney <ben+python@benfinney.id.au>
Date2011-06-07 17:47 +1000
Message-ID<871uz613rl.fsf@benfinney.id.au>
In reply to#7132
Steven D'Aprano <steve+comp.lang.python@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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web