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


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

print function and unwanted trailing space

Started bycandide <candide@free.invalid>
First post2013-08-31 10:17 +0200
Last post2013-09-12 15:25 -0400
Articles 20 on this page of 22 — 11 participants

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


Contents

  print function and unwanted trailing space candide <candide@free.invalid> - 2013-08-31 10:17 +0200
    Re: print function and unwanted trailing space Andreas Perstinger <andipersti@gmail.com> - 2013-08-31 10:43 +0200
      Re: print function and unwanted trailing space candide <candide@free.invalid> - 2013-08-31 11:25 +0200
        Re: print function and unwanted trailing space Peter Otten <__peter__@web.de> - 2013-08-31 12:31 +0200
          Re: print function and unwanted trailing space candide <candide@free.invalid> - 2013-08-31 15:33 +0200
            Re: print function and unwanted trailing space Peter Otten <__peter__@web.de> - 2013-08-31 15:59 +0200
              Re: print function and unwanted trailing space candide <candide@free.invalid> - 2013-08-31 17:58 +0200
            Re: print function and unwanted trailing space Chris Angelico <rosuav@gmail.com> - 2013-09-01 01:30 +1000
            Re: print function and unwanted trailing space Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-08-31 16:43 +0100
            Re: print function and unwanted trailing space Chris Angelico <rosuav@gmail.com> - 2013-09-01 08:08 +1000
            Re: print function and unwanted trailing space Joshua Landau <joshua@landau.ws> - 2013-09-01 00:15 +0100
            Re: print function and unwanted trailing space Terry Reedy <tjreedy@udel.edu> - 2013-08-31 19:57 -0400
          Re: print function and unwanted trailing space candide <candide@free.invalid> - 2013-08-31 17:51 +0200
    Re: print function and unwanted trailing space Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-08-31 11:16 +0000
      Re: print function and unwanted trailing space Peter Otten <__peter__@web.de> - 2013-08-31 14:27 +0200
      Re: print function and unwanted trailing space Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-08-31 13:37 +0100
      Re: print function and unwanted trailing space candide <candide@free.invalid> - 2013-08-31 14:59 +0200
        Re: print function and unwanted trailing space Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-08-31 15:18 +0000
    Re: print function and unwanted trailing space Ned Batchelder <ned@nedbatchelder.com> - 2013-08-31 07:24 -0400
      Re: print function and unwanted trailing space candide <candide@free.invalid> - 2013-08-31 15:51 +0200
    Re: print function and unwanted trailing space Wayne Werner <wayne@waynewerner.com> - 2013-09-11 06:36 -0500
    Re: print function and unwanted trailing space Albert Hopkins <marduk@letterboxes.org> - 2013-09-12 15:25 -0400

Page 1 of 2  [1] 2  Next page →


#53335 — print function and unwanted trailing space

Fromcandide <candide@free.invalid>
Date2013-08-31 10:17 +0200
Subjectprint function and unwanted trailing space
Message-ID<5221a693$0$2059$426a74cc@news.free.fr>
What is the equivalent in Python 3 to the following Python 2 code:

# -----------------------------
for i in range(5):
     print i,
# -----------------------------

?

Be careful that the above code doesn't add a trailing space after the 
last number in the list, hence the following Python 3 code isn't 
strictly equivalent:


# -----------------------------
for i in range(5):
     print(i, end=' ')   # <- The last ' ' is unwanted
print()
# -----------------------------

[toc] | [next] | [standalone]


#53338

FromAndreas Perstinger <andipersti@gmail.com>
Date2013-08-31 10:43 +0200
Message-ID<mailman.405.1377938644.19984.python-list@python.org>
In reply to#53335
On 31.08.2013 10:17, candide wrote:
>
> What is the equivalent in Python 3 to the following Python 2 code:
>
> # -----------------------------
> for i in range(5):
>       print i,
> # -----------------------------
>
> ?

How about

 >>> print(" ".join(str(i) for i in range(5)))
0 1 2 3 4

Bye, Andreas


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


#53339

Fromcandide <candide@free.invalid>
Date2013-08-31 11:25 +0200
Message-ID<5221b68b$0$2280$426a74cc@news.free.fr>
In reply to#53338
Le 31/08/2013 10:43, Andreas Perstinger a écrit :

 > How about
 >
 >  >>> print(" ".join(str(i) for i in range(5)))
 > 0 1 2 3 4
 >


Thanks for your answer. The output is stricly the same but the code 
doesn't suit my needs :

1) I'm porting to Python 3 a Python 2 full beginner course : the 
learners are not aware of the join method nor the str type nor 
generators stuff;
2) Your code introduce a (sometimes) useless conversion to str (consider 
a string instead of range(5)).

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


#53341

FromPeter Otten <__peter__@web.de>
Date2013-08-31 12:31 +0200
Message-ID<mailman.406.1377945101.19984.python-list@python.org>
In reply to#53339
candide wrote:

> Le 31/08/2013 10:43, Andreas Perstinger a écrit :
> 
>  > How about
>  >
>  >  >>> print(" ".join(str(i) for i in range(5)))
>  > 0 1 2 3 4
>  >
> 
> 
> Thanks for your answer. The output is stricly the same but the code
> doesn't suit my needs :
> 
> 1) I'm porting to Python 3 a Python 2 full beginner course : the
> learners are not aware of the join method nor the str type nor
> generators stuff;
> 2) Your code introduce a (sometimes) useless conversion to str (consider
> a string instead of range(5)).

You are out of luck, the softspace mechanism, roughly

softspace = False
for i in range(5):
    if softspace:
        print(end=" ")
    print(i, end="")
    softspace = True
print()

with `softspace` saved as a file attribute, is gone in Python3. But I don't 
think that someone who doesn't know it existed will miss the feature.

Maybe you can allow for /some/ magic and introduce your students to

print(*range(5))

early-on.

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


#53354

Fromcandide <candide@free.invalid>
Date2013-08-31 15:33 +0200
Message-ID<5221f0af$0$2412$426a34cc@news.free.fr>
In reply to#53341
Le 31/08/2013 12:31, Peter Otten a écrit :
 > softspace = False
 > for i in range(5):
 >      if softspace:
 >          print(end=" ")
 >      print(i, end="")
 >      softspace = True
 > print()


The if instruction imposes useless testing (we know in advance the 
problem to occur at the very end of the loop) and useless writing 
(writing '').

The following is clearer

# -------------------------
n=5
for i in range(n-1):
     print(i, end=' ')
print(n-1)
# -------------------------


but doesn't solve all the cases (imagine a string or an iterator).

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


#53356

FromPeter Otten <__peter__@web.de>
Date2013-08-31 15:59 +0200
Message-ID<mailman.412.1377957573.19984.python-list@python.org>
In reply to#53354
candide wrote:

> Le 31/08/2013 12:31, Peter Otten a écrit :
>  > softspace = False
>  > for i in range(5):
>  >      if softspace:
>  >          print(end=" ")
>  >      print(i, end="")
>  >      softspace = True
>  > print()
> 
> 
> The if instruction imposes useless testing (we know in advance the
> problem to occur at the very end of the loop) and useless writing
> (writing '').

To make it crystal clear, the above was to illustrate the algorithm used in 
Python 2, not a suggestion. Python 2 uses that "useless testing" -- which is 
cheap compared to actual I/O.

> The following is clearer
> 
> # -------------------------
> n=5
> for i in range(n-1):
>      print(i, end=' ')
> print(n-1)
> # -------------------------
> 
> 
> but doesn't solve all the cases (imagine a string or an iterator).

I still think you should live with a trailing space or go with my actual 
suggestion

print(*range(5))

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


#53369

Fromcandide <candide@free.invalid>
Date2013-08-31 17:58 +0200
Message-ID<522212bf$0$2323$426a74cc@news.free.fr>
In reply to#53356
Le 31/08/2013 15:59, Peter Otten a écrit :


>
> To make it crystal clear, the above was to illustrate the algorithm used in
> Python 2, not a suggestion.


Ok sorry, I misinterpreted.




 > I still think you should live with a trailing space


Are you sure ? The following code

#----------------------------------
import io

output = io.StringIO()
n=5
for i in range(n-1):
     print(i, end=' ', file=output)
print(n-1, file=output)
print(output.getvalue().count(' '))
#----------------------------------


outputs 4, the correct number of space character.



 > or go with my actual
 > suggestion
 >
 > print(*range(5))
 >


It's a very good suggestion (the best one in fact) but rather 
complicated to explain to pure novices in programming.

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


#53365

FromChris Angelico <rosuav@gmail.com>
Date2013-09-01 01:30 +1000
Message-ID<mailman.415.1377963057.19984.python-list@python.org>
In reply to#53354
On Sat, Aug 31, 2013 at 11:33 PM, candide <candide@free.invalid> wrote:
> The if instruction imposes useless testing (we know in advance the problem
> to occur at the very end of the loop) and useless writing (writing '').
>
> The following is clearer
>
> # -------------------------
> n=5
> for i in range(n-1):
>     print(i, end=' ')
> print(n-1)
> # -------------------------
>
>
> but doesn't solve all the cases (imagine a string or an iterator).

Similar but maybe simpler, and copes with more arbitrary iterables:

it=iter(range(5))
print(next(it), end='')
for i in it:
    print('',i, end='')

Also guarantees to use 'sep' between the elements, fwiw.

ChrisA

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


#53366

FromOscar Benjamin <oscar.j.benjamin@gmail.com>
Date2013-08-31 16:43 +0100
Message-ID<mailman.416.1377963862.19984.python-list@python.org>
In reply to#53354
On 31 August 2013 16:30, Chris Angelico <rosuav@gmail.com> wrote:
>>
>> but doesn't solve all the cases (imagine a string or an iterator).
>
> Similar but maybe simpler, and copes with more arbitrary iterables:
>
> it=iter(range(5))
> print(next(it), end='')
> for i in it:
>     print('',i, end='')

If you want to work with arbitrary iterables then you'll want

it = iter(iterable)
try:
    val = next(it)
except StopIteration:
    pass  # Or raise or something?
else:
    print(val, end='')
for i in it:
    print('', i, end='')


Oscar

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


#53376

FromChris Angelico <rosuav@gmail.com>
Date2013-09-01 08:08 +1000
Message-ID<mailman.422.1377986886.19984.python-list@python.org>
In reply to#53354
On Sun, Sep 1, 2013 at 1:43 AM, Oscar Benjamin
<oscar.j.benjamin@gmail.com> wrote:
> On 31 August 2013 16:30, Chris Angelico <rosuav@gmail.com> wrote:
>>>
>>> but doesn't solve all the cases (imagine a string or an iterator).
>>
>> Similar but maybe simpler, and copes with more arbitrary iterables:
>>
>> it=iter(range(5))
>> print(next(it), end='')
>> for i in it:
>>     print('',i, end='')
>
> If you want to work with arbitrary iterables then you'll want
>
> it = iter(iterable)
> try:
>     val = next(it)
> except StopIteration:
>     pass  # Or raise or something?
> else:
>     print(val, end='')
> for i in it:
>     print('', i, end='')

I went with this version:

except StopIteration:
    raise

In other words, if it's going to bomb, let it bomb :)

ChrisA

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


#53378

FromJoshua Landau <joshua@landau.ws>
Date2013-09-01 00:15 +0100
Message-ID<mailman.424.1377990970.19984.python-list@python.org>
In reply to#53354
On 31 August 2013 23:08, Chris Angelico <rosuav@gmail.com> wrote:
> On Sun, Sep 1, 2013 at 1:43 AM, Oscar Benjamin
> <oscar.j.benjamin@gmail.com> wrote:
>> On 31 August 2013 16:30, Chris Angelico <rosuav@gmail.com> wrote:
>>>>
>>>> but doesn't solve all the cases (imagine a string or an iterator).
>>>
>>> Similar but maybe simpler, and copes with more arbitrary iterables:
>>>
>>> it=iter(range(5))
>>> print(next(it), end='')
>>> for i in it:
>>>     print('',i, end='')
>>
>> If you want to work with arbitrary iterables then you'll want
>>
>> it = iter(iterable)
>> try:
>>     val = next(it)
>> except StopIteration:
>>     pass  # Or raise or something?
>> else:
>>     print(val, end='')
>> for i in it:
>>     print('', i, end='')
>
> I went with this version:
>
> except StopIteration:
>     raise
>
> In other words, if it's going to bomb, let it bomb :)

I think the point is that StopIteration is an unsafe error to raise.

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


#53383

FromTerry Reedy <tjreedy@udel.edu>
Date2013-08-31 19:57 -0400
Message-ID<mailman.429.1377993482.19984.python-list@python.org>
In reply to#53354
On 8/31/2013 7:15 PM, Joshua Landau wrote:
> On 31 August 2013 23:08, Chris Angelico <rosuav@gmail.com> wrote:
>> On Sun, Sep 1, 2013 at 1:43 AM, Oscar Benjamin
>> <oscar.j.benjamin@gmail.com> wrote:
>>> On 31 August 2013 16:30, Chris Angelico <rosuav@gmail.com> wrote:
>>>>>
>>>>> but doesn't solve all the cases (imagine a string or an iterator).
>>>>
>>>> Similar but maybe simpler, and copes with more arbitrary iterables:
>>>>
>>>> it=iter(range(5))
>>>> print(next(it), end='')
>>>> for i in it:
>>>>      print('',i, end='')
>>>
>>> If you want to work with arbitrary iterables then you'll want
>>>
>>> it = iter(iterable)
>>> try:
>>>      val = next(it)
>>> except StopIteration:
>>>      pass  # Or raise or something?
>>> else:
>>>      print(val, end='')
>>> for i in it:
>>>      print('', i, end='')
>>
>> I went with this version:
>>
>> except StopIteration:
>>      raise
>>
>> In other words, if it's going to bomb, let it bomb :)
>
> I think the point is that StopIteration is an unsafe error to raise.

It should only be raised by iterator.__next__ method and caught by 
iterator user and not re-raised. Raise something like "ValueError('empty 
iterable') from None" instead.


-- 
Terry Jan Reedy

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


#53368

Fromcandide <candide@free.invalid>
Date2013-08-31 17:51 +0200
Message-ID<522210f8$0$13987$426a74cc@news.free.fr>
In reply to#53341
Le 31/08/2013 12:31, Peter Otten a écrit :

> with `softspace` saved as a file attribute, is gone in Python3.


After reading

http://docs.python.org/3.0/whatsnew/3.0.html#print-is-a-function


I understand what you meant by "softspace". Thanks.

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


#53342

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-08-31 11:16 +0000
Message-ID<5221d090$0$6599$c3e8da3$5496439d@news.astraweb.com>
In reply to#53335
On Sat, 31 Aug 2013 10:17:23 +0200, candide wrote:

> What is the equivalent in Python 3 to the following Python 2 code:
> 
> # -----------------------------
> for i in range(5):
>      print i,
> # -----------------------------
> 
> ?
> 
> Be careful that the above code doesn't add a trailing space after the
> last number in the list, 

Of course it does. Have you actually tried it? The interactive 
interpreter is tricky, because you cannot directly follow a for-loop with 
another statement. If you try, the interactive interpreter gives you an 
indentation error. But we can work around it by sticking everything 
inside an if block, like so:

py> if True:
...     for i in range(5):
...             print i,
...     # could be pages of code here
...     print "FINISHED"
...
0 1 2 3 4 FINISHED


Or you could stick the code inside an exec, which doesn't have the same 
limitation as the interactive interpreter. This mimics the behaviour of 
code in a file:

py> exec """for i in range(5):
...     print i,
... print "FINISHED"
... """
0 1 2 3 4 FINISHED


The same results occur with any other Python 2.x, and indeed all the way 
back to Python 1.5 and older.


> hence the following Python 3 code isn't strictly equivalent:
> 
> 
> # -----------------------------
> for i in range(5):
>      print(i, end=' ')   # <- The last ' ' is unwanted
> print()


The last space is exactly the same as you get in Python 2. But really, 
who cares about an extra invisible space? In non-interactive mode, the 
two are exactly the same (ignoring the extra print() call outside the 
loop), but even at the interactive interpreter, I'd like to see the code 
where an extra space makes a real difference.



-- 
Steven

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


#53346

FromPeter Otten <__peter__@web.de>
Date2013-08-31 14:27 +0200
Message-ID<mailman.408.1377952066.19984.python-list@python.org>
In reply to#53342
Steven D'Aprano wrote:

> On Sat, 31 Aug 2013 10:17:23 +0200, candide wrote:
> 
>> What is the equivalent in Python 3 to the following Python 2 code:
>> 
>> # -----------------------------
>> for i in range(5):
>>      print i,
>> # -----------------------------
>> 
>> ?
>> 
>> Be careful that the above code doesn't add a trailing space after the
>> last number in the list,
> 
> Of course it does. Have you actually tried it? The interactive
> interpreter is tricky, because you cannot directly follow a for-loop with
> another statement. If you try, the interactive interpreter gives you an
> indentation error. But we can work around it by sticking everything
> inside an if block, like so:
> 
> py> if True:
> ...     for i in range(5):
> ...             print i,
> ...     # could be pages of code here
> ...     print "FINISHED"
> ...
> 0 1 2 3 4 FINISHED
> 
> 
> Or you could stick the code inside an exec, which doesn't have the same
> limitation as the interactive interpreter. This mimics the behaviour of
> code in a file:
> 
> py> exec """for i in range(5):
> ...     print i,
> ... print "FINISHED"
> ... """
> 0 1 2 3 4 FINISHED
> 
> 
> The same results occur with any other Python 2.x, and indeed all the way
> back to Python 1.5 and older.

Your test is flawed. The softspace mechanism ensures that there is a space 
*between* all printed items, but not *after* the last printed item.

print "FINISHED"

will add a space while

print

will not. Compare:

>>> with open("tmp.txt", "w") as f:
...     for i in range(3): print >> f, i,
...     print >> f
... 
>>> open("tmp.txt").read()
'0 1 2\n'
>>> with open("tmp.txt", "w") as f:
...     for i in range(3): print >> f, i,
...     print >> f, "FINISHED"
... 
>>> open("tmp.txt").read()
'0 1 2 FINISHED\n'



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


#53347

FromOscar Benjamin <oscar.j.benjamin@gmail.com>
Date2013-08-31 13:37 +0100
Message-ID<mailman.410.1377952706.19984.python-list@python.org>
In reply to#53342
On 31 August 2013 12:16, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> On Sat, 31 Aug 2013 10:17:23 +0200, candide wrote:
>
>> What is the equivalent in Python 3 to the following Python 2 code:
>>
>> # -----------------------------
>> for i in range(5):
>>      print i,
>> # -----------------------------
>>
>> ?
>>
>> Be careful that the above code doesn't add a trailing space after the
>> last number in the list,
>
> Of course it does. Have you actually tried it? The interactive
> interpreter is tricky, because you cannot directly follow a for-loop with
> another statement. If you try, the interactive interpreter gives you an
> indentation error. But we can work around it by sticking everything
> inside an if block, like so:
>
> py> if True:
> ...     for i in range(5):
> ...             print i,
> ...     # could be pages of code here
> ...     print "FINISHED"
> ...
> 0 1 2 3 4 FINISHED

The space is added by the final print statement, not the last one in
the loop. Here's a demo that shows this:

$ cat print.py
for i in range(5):
    print i,
print
$ cat print3.py
for i in range(5):
    print(i, end=' ')
print()
$ py -2.7 print.py | cat -A
0 1 2 3 4^M$
$ py -3.3 print3.py | cat -A
0 1 2 3 4 ^M$

(Notice the space between the 4 and ^M (which is cat's way of saying '\r').

[snip]
>
>> hence the following Python 3 code isn't strictly equivalent:
>>
>>
>> # -----------------------------
>> for i in range(5):
>>      print(i, end=' ')   # <- The last ' ' is unwanted
>> print()
>
> The last space is exactly the same as you get in Python 2. But really,
> who cares about an extra invisible space? In non-interactive mode, the
> two are exactly the same (ignoring the extra print() call outside the
> loop), but even at the interactive interpreter, I'd like to see the code
> where an extra space makes a real difference.

I seem to remember it breaking some unit test or doc test something
when I first tried to port something using 2to3 (this is the
replacement that 2to3 uses for print with a trailing comma). It's not
so important for interactive terminal output but when you do 'python
script.py > output.dat' the unwanted space shouldn't be there. The
soft-space feature is useful but stateful as Peter says and defies the
normal concept of what happens when calling a function so it was
removed when print became a function.


Oscar

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


#53352

Fromcandide <candide@free.invalid>
Date2013-08-31 14:59 +0200
Message-ID<5221e8a5$0$2105$426a74cc@news.free.fr>
In reply to#53342
Le 31/08/2013 13:16, Steven D'Aprano a écrit :

>
> Of course it does. Have you actually tried it?


Of course I did, redirecting the output to a file in order to spot an 
eventually trailing space. I did the same for the Python 3 code.

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


#53363

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-08-31 15:18 +0000
Message-ID<5222092a$0$6599$c3e8da3$5496439d@news.astraweb.com>
In reply to#53352
On Sat, 31 Aug 2013 14:59:17 +0200, candide wrote:

> Le 31/08/2013 13:16, Steven D'Aprano a écrit :
> 
> 
>> Of course it does. Have you actually tried it?
> 
> 
> Of course I did, redirecting the output to a file in order to spot an
> eventually trailing space. I did the same for the Python 3 code.


Fair enough. Seems like the print statement implementation in Python 2 is 
uglier than I imagined, keeping hidden state between invocations.



-- 
Steven

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


#53343

FromNed Batchelder <ned@nedbatchelder.com>
Date2013-08-31 07:24 -0400
Message-ID<mailman.407.1377948297.19984.python-list@python.org>
In reply to#53335
On 8/31/13 4:17 AM, candide wrote:
>
> What is the equivalent in Python 3 to the following Python 2 code:
>
> # -----------------------------
> for i in range(5):
>     print i,
> # -----------------------------
>
> ?
>
> Be careful that the above code doesn't add a trailing space after the 
> last number in the list, hence the following Python 3 code isn't 
> strictly equivalent:
>
>
> # -----------------------------
> for i in range(5):
>     print(i, end=' ')   # <- The last ' ' is unwanted
> print()
> # -----------------------------

For a beginner course, the trailing space is fine, use this code. 
They'll never notice the trailing space (I wouldn't have!) and to 
explain why the comma leaves off the last one takes a really advanced 
understanding of obscure details anyway.

--Ned.

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


#53355

Fromcandide <candide@free.invalid>
Date2013-08-31 15:51 +0200
Message-ID<5221f4d3$0$2051$426a74cc@news.free.fr>
In reply to#53343
Le 31/08/2013 13:24, Ned Batchelder a écrit :

> For a beginner course, the trailing space is fine, use this code.

I was really expecting there was a trick but I'll follow your advice, 
after all the trailing space is invisible!

Nevertheless, this can be quite annoying. For instance, some automated 
program testing (cf. http://www.spoj.com/, http://acm.timus.ru/, etc) 
expect the exact output to get accepted, no byte more or a byte less.




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


Page 1 of 2  [1] 2  Next page →

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


csiph-web