Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #9093 > unrolled thread
| Started by | Andrew Berg <bahamutzero8825@gmail.com> |
|---|---|
| First post | 2011-07-08 15:18 -0500 |
| Last post | 2011-07-09 15:12 +1000 |
| Articles | 19 — 9 participants |
Back to article view | Back to comp.lang.python
String concatenation vs. string formatting Andrew Berg <bahamutzero8825@gmail.com> - 2011-07-08 15:18 -0500
Re: String concatenation vs. string formatting John Gordon <gordon@panix.com> - 2011-07-08 20:23 +0000
Re: String concatenation vs. string formatting Ben Finney <ben+python@benfinney.id.au> - 2011-07-09 08:50 +1000
Re: String concatenation vs. string formatting Ben Finney <ben+python@benfinney.id.au> - 2011-07-09 09:15 +1000
Re: String concatenation vs. string formatting Thorsten Kampe <thorsten@thorstenkampe.de> - 2011-07-09 06:23 +0200
Re: String concatenation vs. string formatting Andrew Berg <bahamutzero8825@gmail.com> - 2011-07-10 01:45 -0500
Re: String concatenation vs. string formatting Ben Finney <ben+python@benfinney.id.au> - 2011-07-10 17:07 +1000
Re: String concatenation vs. string formatting Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-07-10 23:42 +1000
Re: String concatenation vs. string formatting Roy Smith <roy@panix.com> - 2011-07-10 10:33 -0400
Re: String concatenation vs. string formatting Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-07-11 08:48 +1000
Re: String concatenation vs. string formatting Andrew Berg <bahamutzero8825@gmail.com> - 2011-07-10 18:24 -0500
Re: String concatenation vs. string formatting Billy Mays <noway@nohow.com> - 2011-07-08 16:57 -0400
Re: String concatenation vs. string formatting Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-07-09 15:30 +1000
Re: String concatenation vs. string formatting Ian Kelly <ian.g.kelly@gmail.com> - 2011-07-09 00:04 -0600
Re: String concatenation vs. string formatting Chris Angelico <rosuav@gmail.com> - 2011-07-09 16:16 +1000
Re: String concatenation vs. string formatting Ian Kelly <ian.g.kelly@gmail.com> - 2011-07-09 00:29 -0600
Re: String concatenation vs. string formatting Ben Finney <ben+python@benfinney.id.au> - 2011-07-09 08:59 +1000
Re: String concatenation vs. string formatting Andrew Berg <bahamutzero8825@gmail.com> - 2011-07-08 18:29 -0500
Re: String concatenation vs. string formatting Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-07-09 15:12 +1000
| From | Andrew Berg <bahamutzero8825@gmail.com> |
|---|---|
| Date | 2011-07-08 15:18 -0500 |
| Subject | String concatenation vs. string formatting |
| Message-ID | <mailman.785.1310156331.1164.python-list@python.org> |
Is it bad practice to use this
> logger.error(self.preset_file + ' could not be stored - ' +
> sys.exc_info()[1])
Instead of this?
> logger.error('{file} could not be stored -
> {error}'.format(file=self.preset_file, error=sys.exc_info()[1]))
Other than the case where a variable isn't a string (format() converts
variables to strings, automatically, right?) and when a variable is used
a bunch of times, concatenation is fine, but somehow, it seems wrong.
Sorry if this seems a bit silly, but I'm a novice when it comes to
design. Plus, there's not really supposed to be "more than one way to do
it" in Python.
[toc] | [next] | [standalone]
| From | John Gordon <gordon@panix.com> |
|---|---|
| Date | 2011-07-08 20:23 +0000 |
| Message-ID | <iv7p0o$nup$1@reader1.panix.com> |
| In reply to | #9093 |
In <mailman.785.1310156331.1164.python-list@python.org> Andrew Berg <bahamutzero8825@gmail.com> writes:
> Is it bad practice to use this
> > logger.error(self.preset_file + ' could not be stored - ' +
> > sys.exc_info()[1])
> Instead of this?
> > logger.error('{file} could not be stored -
> > {error}'.format(file=self.preset_file, error=sys.exc_info()[1]))
> Other than the case where a variable isn't a string (format() converts
> variables to strings, automatically, right?) and when a variable is used
> a bunch of times, concatenation is fine, but somehow, it seems wrong.
> Sorry if this seems a bit silly, but I'm a novice when it comes to
> design. Plus, there's not really supposed to be "more than one way to do
> it" in Python.
Concatenation feels ugly/clunky to me.
I prefer this usage:
logger.error('%s could not be stored - %s' % \
(self.preset_file, sys.exc_info()[1]))
--
John Gordon A is for Amy, who fell down the stairs
gordon@panix.com B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"
[toc] | [prev] | [next] | [standalone]
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2011-07-09 08:50 +1000 |
| Message-ID | <87box4ie04.fsf@benfinney.id.au> |
| In reply to | #9094 |
John Gordon <gordon@panix.com> writes:
> I prefer this usage:
>
> logger.error('%s could not be stored - %s' % \
> (self.preset_file, sys.exc_info()[1]))
That can be improved by learning two things:
* The backslash-linebreak is ugly and fragile, and almost never needed,
since Python knows to continue a statement if any bracketing syntax
(parens, brackets, braces, triple quotes, etc.) is still open.
So you can continue a statement over multiple lines by introducing
some bracketing syntax at an appropriate place. In this case, you
don't even need to add any bracketing syntax, since the function
parens are still open.
* The ‘%’ string formatting operator is superseded in current Python
versions by the more flexible ‘format’ method of string objects.
So:
logger.error(
'{0} could not be stored - {1}'.format(
(self.preset_file, sys.exc_info()[1]))
I usually prefer to use named placeholders instead of positional, but
this duplicates your original.
--
\ “We have clumsy, sputtering, inefficient brains…. It is a |
`\ *struggle* to be rational and objective, and failures are not |
_o__) evidence for an alternative reality.” —Paul Z. Myers, 2010-10-14 |
Ben Finney
[toc] | [prev] | [next] | [standalone]
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2011-07-09 09:15 +1000 |
| Message-ID | <8739igicte.fsf@benfinney.id.au> |
| In reply to | #9097 |
Ben Finney <ben+python@benfinney.id.au> writes:
> logger.error(
> '{0} could not be stored - {1}'.format(
> (self.preset_file, sys.exc_info()[1]))
>
> I usually prefer to use named placeholders instead of positional, but
> this duplicates your original.
Ah, I see that the OP *did* use named placeholders. So, even better:
logger.error(
'{file} could not be stored - {error}'.format(
file=self.preset_file, error=sys.exc_info()[1]))
--
\ “Those who write software only for pay should go hurt some |
`\ other field.” —Erik Naggum, in _gnu.misc.discuss_ |
_o__) |
Ben Finney
[toc] | [prev] | [next] | [standalone]
| From | Thorsten Kampe <thorsten@thorstenkampe.de> |
|---|---|
| Date | 2011-07-09 06:23 +0200 |
| Message-ID | <MPG.2881f638b8d1b46698982d@news.individual.de> |
| In reply to | #9094 |
* John Gordon (Fri, 8 Jul 2011 20:23:52 +0000 (UTC))
> I prefer this usage:
>
> logger.error('%s could not be stored - %s' % \
> (self.preset_file, sys.exc_info()[1]))
The syntax for formatting logging messages according to the
documentation is:
Logger.error(msg, *args)
NOT
Logger.error(msg % (*args))
Thorsten
[toc] | [prev] | [next] | [standalone]
| From | Andrew Berg <bahamutzero8825@gmail.com> |
|---|---|
| Date | 2011-07-10 01:45 -0500 |
| Message-ID | <mailman.828.1310280324.1164.python-list@python.org> |
| In reply to | #9094 |
-----BEGIN PGP SIGNED MESSAGE----- Hash: RIPEMD160 How should I go about switching from concatenation to string formatting for this? avs.write(demux_filter + field_filter + fpsin_filter + i2pfilter + dn_filter + fpsout_filter + trim_filter + info_filter) I can think of a few ways, but none of them are pretty. - -- CPython 3.2 | Windows NT 6.1.7601.17592 | Thunderbird 5.0 PGP/GPG Public Key ID: 0xF88E034060A78FCB -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQEcBAEBAwAGBQJOGUp7AAoJEPiOA0Bgp4/L3koIAMntYStREGjww6yKGKE/xI0W ecAg2BHdqBxTFsPT6NMrSRyrNbdfnWRQcRi/0Z+Hhbwqp4qsz5hDFgsoVPkT5gyj 6q0TeJqaSE+Uoj5g2BofqVlWydyQ7fW34KaANbj7V71/UqXXgb+fl8TYvVRJbg0A KlfytOO0HBrDW8f6dzGZuxLxCb3EONt7buIUV3Pa7b9jQZNTTiOKktLtWAteMMiC CHivQhqzB8/cNVddpyk5LaMEDzJ9yz8a83fjuK8F5E/wrYk22t6Fad6PKgDEivaj hAiE5HMeUw+gQ7xFhJGkK31/KyHRqAaFR4mUh16u9GHMTaGPobk8NEj81LwCbvg= =g3kL -----END PGP SIGNATURE-----
[toc] | [prev] | [next] | [standalone]
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2011-07-10 17:07 +1000 |
| Message-ID | <87r55yfwae.fsf@benfinney.id.au> |
| In reply to | #9152 |
[Multipart message — attachments visible in raw view] — view raw
Andrew Berg <bahamutzero8825@gmail.com> writes:
> How should I go about switching from concatenation to string formatting
> for this?
>
> avs.write(demux_filter + field_filter + fpsin_filter + i2pfilter +
> dn_filter + fpsout_filter + trim_filter + info_filter)
A direct replacement would be:
avs.write(
"{demux_filter}{field_filter}{fpsin_filter}{i2pfilter}"
"{dn_filter}{fpsout_filter}{trim_filter}{info_filter}".format(**vars()))
The presence of all those separate names for similar things, though,
is a code smell. A collection of similar-purpose objects used in a
single place deserves a collection.
If that collection is a dictionary, which I can show with a
straightforward implementation (that will likely be put together in a
more appropriate way in your program)::
filter_names = [
"demux", "field", "fpsin", "i2p",
"dn", "fpsout", "trim", "info"]
filters = dict(
(name, FooFilter(name))
for name in filter_names)
then the ‘avs.write’ call above can take a format string prepared from
the names already defined::
# … do a bunch of stuff with the filters …
avs_output_template = "".join(
"{{{name}}}".format(name=name) for name in filter_names)
avs.write(avs_output_template.format(**filters))
# … do a bunch of other stuff with the filters …
An aside: bear in mind that the name ‘filter’ is a Python built-in, so
if you re-bind that name you're shadowing the built-in object.
Having re-factored to that point, I'd then be asking what purpose is
being served by concatenating string representations of these objects
together like that, and ask whether that purpose is better served some
other way.
> I can think of a few ways, but none of them are pretty.
Most of the above probably needs to be done (perhaps not exactly as I've
done it) to improve the design of the program anyway.
--
\ “I took it easy today. I just pretty much layed around in my |
`\ underwear all day. … Got kicked out of quite a few places, |
_o__) though.” —Bug-Eyed Earl, _Red Meat_ |
Ben Finney
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-07-10 23:42 +1000 |
| Message-ID | <4e19ac59$0$29977$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #9152 |
Andrew Berg wrote:
> How should I go about switching from concatenation to string formatting
> for this?
>
> avs.write(demux_filter + field_filter + fpsin_filter + i2pfilter +
> dn_filter + fpsout_filter + trim_filter + info_filter)
>
> I can think of a few ways, but none of them are pretty.
fields = (demux_filter, field_filter, fpsin_filter, i2pfilter,
dn_filter, fpsout_filter, trim_filter, info_filter)
avs.write("%s"*len(fields) % fields)
works for me.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2011-07-10 10:33 -0400 |
| Message-ID | <roy-0D981D.10330810072011@news.panix.com> |
| In reply to | #9152 |
In article <mailman.828.1310280324.1164.python-list@python.org>,
Andrew Berg <bahamutzero8825@gmail.com> wrote:
> How should I go about switching from concatenation to string formatting
> for this?
>
> avs.write(demux_filter + field_filter + fpsin_filter + i2pfilter +
> dn_filter + fpsout_filter + trim_filter + info_filter)
>
> I can think of a few ways, but none of them are pretty.
The canonical way to do that would be something like
fields = [demux_filter,
field_filter,
fpsin_filter,
i2pfilter,
dn_filter,
fpsout_filter,
trim_filter,
info_filter]
avs.write(''.join(fields))
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-07-11 08:48 +1000 |
| Message-ID | <4e1a2c3e$0$29966$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #9165 |
Roy Smith wrote:
> The canonical way to do that would be something like
>
> fields = [demux_filter,
> field_filter,
> fpsin_filter,
> i2pfilter,
> dn_filter,
> fpsout_filter,
> trim_filter,
> info_filter]
> avs.write(''.join(fields))
I can't believe I didn't think of that. I must be getting sick. (The sore
throat, stuffy nose and puffy eyes may also be a sign.)
Yes, ''.join() is far to be preferred over my solution using "%s".
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Andrew Berg <bahamutzero8825@gmail.com> |
|---|---|
| Date | 2011-07-10 18:24 -0500 |
| Message-ID | <mailman.862.1310340301.1164.python-list@python.org> |
| In reply to | #9165 |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: RIPEMD160
On 2011.07.10 09:33 AM, Roy Smith wrote:
> The canonical way to do that would be something like
>
> fields = [demux_filter, field_filter, fpsin_filter, i2pfilter,
> dn_filter, fpsout_filter, trim_filter, info_filter]
> avs.write(''.join(fields))
That would look really awful (IMO) if the strings weren't intended to be
on separate lines (I use embedded newlines instead of joining them with
newlines in order to prevent blank lines whenever a certain filter isn't
used). In this particular case, they are, so even though it uses a lot
of whitespace, it does match the layout of its output.
- --
CPython 3.2 | Windows NT 6.1.7601.17592 | Thunderbird 5.0
PGP/GPG Public Key ID: 0xF88E034060A78FCB
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iQEcBAEBAwAGBQJOGjSxAAoJEPiOA0Bgp4/LHzcH+gKeSCkbdEh8jg2UV0vICJdS
Fea95/vqCbZkjQxSuW8L73CpoACiv4XQ6hoxyIUq7maf+W89rGMVmLsPWYXtmif9
FV6WM3kSpg4hoC1cbqGW5g1bnpMnSPlznm74mKtdGhF+3zEtlm9+j8m53362YQHc
0Y9D+4KAeee5QUT/NII5QBRvSG2rAuv5+sayMNayix0pCJLEGrRLp/7LJOyhvJLN
eDdywE+svfcQAi4iGAylrmvDfgf6pBgysyY/pv2YD9IpdpYL5mkVqLi+ADZdZBOb
M4uxBReowgC/RaWxB+qEvfg5AxWmfg4uCtAl48Z/Jv/uYR9d9jeHAlbuV2xPfnk=
=wRB5
-----END PGP SIGNATURE-----
[toc] | [prev] | [next] | [standalone]
| From | Billy Mays <noway@nohow.com> |
|---|---|
| Date | 2011-07-08 16:57 -0400 |
| Message-ID | <iv7qv2$2ar$1@speranza.aioe.org> |
| In reply to | #9093 |
On 07/08/2011 04:18 PM, Andrew Berg wrote:
> Is it bad practice to use this
>> logger.error(self.preset_file + ' could not be stored - ' +
>> sys.exc_info()[1])
> Instead of this?
>> logger.error('{file} could not be stored -
>> {error}'.format(file=self.preset_file, error=sys.exc_info()[1]))
>
>
> Other than the case where a variable isn't a string (format() converts
> variables to strings, automatically, right?) and when a variable is used
> a bunch of times, concatenation is fine, but somehow, it seems wrong.
> Sorry if this seems a bit silly, but I'm a novice when it comes to
> design. Plus, there's not really supposed to be "more than one way to do
> it" in Python.
If it means anything, I think concatenation is faster.
__TIMES__
a() - 0.09s
b() - 0.09s
c() - 54.80s
d() - 5.50s
Code is below:
def a(v):
out = ""
for i in xrange(1000000):
out += v
return len(out)
def b(v):
out = ""
for i in xrange(100000):
out += v+v+v+v+v+v+v+v+v+v
return len(out)
def c(v):
out = ""
for i in xrange(1000000):
out = "%s%s" % (out, v)
return len(out)
def d(v):
out = ""
for i in xrange(100000):
out = "%s%s%s%s%s%s%s%s%s%s%s" % (out,v,v,v,v,v,v,v,v,v,v)
return len(out)
print "a", a('xxxxxxxxxx')
print "b", b('xxxxxxxxxx')
print "c", c('xxxxxxxxxx')
print "d", d('xxxxxxxxxx')
import profile
profile.run("a('xxxxxxxxxx')")
profile.run("b('xxxxxxxxxx')")
profile.run("c('xxxxxxxxxx')")
profile.run("d('xxxxxxxxxx')")
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-07-09 15:30 +1000 |
| Message-ID | <4e17e790$0$29977$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #9095 |
Billy Mays wrote: > If it means anything, I think concatenation is faster. You are measuring the speed of an implementation-specific optimization. You'll likely get *very* different results with Jython or IronPython, or old versions of CPython, or even if you use instance attributes instead of local variables. It also doesn't generalise: only appends are optimized, not prepends. Worse, the optimization can be defeated by accidents of your operating system's memory management, so code that runs snappily and fast on one machine will run SLLLOOOOOOWWWWWWWWWWWWWWWLY on another. This is not a hypothetical risk. People have been burned by this in real life: http://www.gossamer-threads.com/lists/python/dev/771948 If you're interested in learning about the optimization: http://utcc.utoronto.ca/~cks/space/blog/python/ExaminingStringConcatOpt -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-07-09 00:04 -0600 |
| Message-ID | <mailman.793.1310191513.1164.python-list@python.org> |
| In reply to | #9108 |
On Fri, Jul 8, 2011 at 11:30 PM, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > Billy Mays wrote: > >> If it means anything, I think concatenation is faster. > > You are measuring the speed of an implementation-specific optimization. > You'll likely get *very* different results with Jython or IronPython, or > old versions of CPython, or even if you use instance attributes instead of > local variables. > > It also doesn't generalise: only appends are optimized, not prepends. Indeed: $ python -m timeit -s "v = 'x' * 10; out = ''" "out = out + v" 1000000 loops, best of 3: 6.59 usec per loop $ python -m timeit -s "v = 'x' * 10; out = ''" "out = v + out" 100000 loops, best of 3: 268 usec per loop Good to know. I had no idea such an optimization existed. Cheers, Ian
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-07-09 16:16 +1000 |
| Message-ID | <mailman.794.1310192219.1164.python-list@python.org> |
| In reply to | #9108 |
On Sat, Jul 9, 2011 at 3:30 PM, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > It also doesn't generalise: only appends are optimized, not prepends. > > If you're interested in learning about the optimization: > > http://utcc.utoronto.ca/~cks/space/blog/python/ExaminingStringConcatOpt >From that page: "Also, this is only for plain (byte) strings, not for Unicode strings; as of Python 2.4.2, Unicode string concatenation remains un-optimized." Has the same optimization been implemented for Unicode? The page doesn't mention Python 3 at all, and I would guess that the realloc optimization would work fine for both types of string. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-07-09 00:29 -0600 |
| Message-ID | <mailman.795.1310193009.1164.python-list@python.org> |
| In reply to | #9108 |
On Sat, Jul 9, 2011 at 12:16 AM, Chris Angelico <rosuav@gmail.com> wrote: > Has the same optimization been implemented for Unicode? The page > doesn't mention Python 3 at all, and I would guess that the realloc > optimization would work fine for both types of string. Seems to be implemented for strs in 3.2, but not unicode in 2.7.
[toc] | [prev] | [next] | [standalone]
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2011-07-09 08:59 +1000 |
| Message-ID | <877h7sidjq.fsf@benfinney.id.au> |
| In reply to | #9093 |
Andrew Berg <bahamutzero8825@gmail.com> writes:
> Is it bad practice to use this
> > logger.error(self.preset_file + ' could not be stored - ' +
> > sys.exc_info()[1])
This is not necessarily bad practice, but there are not many points in
its favour. It's inflexible and makes the eventual formatting harder to
discern.
> Instead of this?
> > logger.error('{file} could not be stored -
> > {error}'.format(file=self.preset_file, error=sys.exc_info()[1]))
With the caveat that the formatting of that line should be using PEP 8
indentation for clarity:
logger.error(
'{file} could not be stored - {error}'.format(
file=self.preset_file, error=sys.exc_info()[1]))
> Other than the case where a variable isn't a string (format() converts
> variables to strings, automatically, right?)
If you don't specify a conversion in the placeholder, it will default to
‘str’, yes.
> and when a variable is used a bunch of times, concatenation is fine,
I don't see any argument for concatenation there; using a variable a
bunch of times works just fine with the ‘format’ method.
> but somehow, it seems wrong. Sorry if this seems a bit silly, but I'm
> a novice when it comes to design. Plus, there's not really supposed to
> be "more than one way to do it" in Python.
There is often more than one way to do it. The Zen of Python is explicit
that there should be one obvious way to do it (and preferably only one).
The “OOW” in “TOOWTDI” is not “only one way”, but “one obvious way”.
The presence of multiple ways to format strings (the ‘%’ operator, the
‘format’ method) is for backward compatibility with code written before
the current recommended ‘format’ method.
Backward compatibility is a common reason for more than one way to do it
in Python. It's just preferable that all but one of them should be
non-obvious :-)
--
\ “The whole area of [treating source code as intellectual |
`\ property] is almost assuring a customer that you are not going |
_o__) to do any innovation in the future.” —Gary Barnett |
Ben Finney
[toc] | [prev] | [next] | [standalone]
| From | Andrew Berg <bahamutzero8825@gmail.com> |
|---|---|
| Date | 2011-07-08 18:29 -0500 |
| Message-ID | <mailman.789.1310167795.1164.python-list@python.org> |
| In reply to | #9098 |
On 2011.07.08 05:59 PM, Ben Finney wrote: > With the caveat that the formatting of that line should be using PEP 8 > indentation for clarity: PEP 8 isn't bad, but I don't agree with everything in it. Certain lines look good in chunks, some don't, at least to me. It's quite likely I'm going to be writing 98%, if not more, of this project's code, so what looks good to me matters more than a standard (as long as the code works). Obviously, if I need to work in a team, then things change. > > and when a variable is used a bunch of times, concatenation is fine, I prefaced that sentence with "Other than the case", as in "except for the following case(s)". > There is often more than one way to do it. The Zen of Python is explicit > that there should be one obvious way to do it (and preferably only one). I meant in contrast to the idea of intentionally having multiple ways to do something, all with roughly equal merit. On 2011.07.08 04:38 PM, Ian Kelly wrote: > Also, string formatting (especially using the new syntax like you are) > is much clearer because there's less noise (the quotes all over the > place and the plusses) I don't find it that much clearer unless there are a lot of chunks. > and it's better for dealing with internationalization if you need to > do that. I hadn't thought of that. That's probably the best reason to use string formatting. Thanks, everyone.
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-07-09 15:12 +1000 |
| Message-ID | <4e17e348$0$29993$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #9093 |
Andrew Berg wrote:
> Is it bad practice to use this
>> logger.error(self.preset_file + ' could not be stored - ' +
>> sys.exc_info()[1])
> Instead of this?
>> logger.error('{file} could not be stored -
>> {error}'.format(file=self.preset_file, error=sys.exc_info()[1]))
>
>
> Other than the case where a variable isn't a string (format() converts
> variables to strings, automatically, right?)
Not exactly, but more or less. format() has type codes, just like % string
interpolation:
>>> '{0:d}'.format(1)
'1'
>>> '{0:d}'.format(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Unknown format code 'd' for object of type 'str'
>>> '%d' % 1
'1'
>>> '%d' % None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: %d format: a number is required, not NoneType
If you don't give a type code, format converts any object to string (if
possible).
> and when a variable is used
> a bunch of times, concatenation is fine, but somehow, it seems wrong.
I don't like long chains of string concatenation, but short chains seem okay
to me. One or two plus signs seems fine to my eyes, three at the most. Any
more than that, I'd look at replacing it with % interpolation, the
str.join() idiom, the string.Template class, or str.format.
That's five ways of building strings.
Of course, *repeated* string concatenation risks being slow -- not just a
little slow, but potentially MASSIVELY slow, hundreds or thousands of times
slower that alternatives. Fortunately recent versions of CPython tend to
avoid this (which makes it all the more mysterious when the slow-down does
strike), but other Pythons like Jython and IronPython may not. So it's best
to limit string concatenation to one or two strings.
And finally, if you're concatenating string literals, you can use implicit
concatenation (*six* ways):
>>> s = ("hello "
... "world"
... "!")
>>> s
'hello world!'
> Sorry if this seems a bit silly, but I'm a novice when it comes to
> design. Plus, there's not really supposed to be "more than one way to do
> it" in Python.
On the contrary -- there are many different examples of "more than one way
to do it". The claim that Python has "only one way" to do things comes from
the Perl community, and is wrong.
It is true that Python doesn't deliberately add multiple ways of doing
things just for the sake of being different, or because they're cool,
although of course that's a subjective judgement. (Some people think that
functional programming idioms such as map and filter fall into that
category, wrongly in my opinion.) In any case, it's clear that Python
supports many ways of doing "the same thing", not all of which are exactly
equivalent:
# e.g. copy a list
blist = list(alist)
blist = alist[:]
blist[:] = alist # assumes blist already exists
blist = copy.copy(alist)
blist = copy.deepcopy(alist)
blist = []; blist.extend(alist)
blist = [x for x in alist] # don't do this
Hardly "only one way" :)
--
Steven
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web