Why is parenthesis in print voluntary in Python 2.7?

92,860

Solution 1

In Python 2.x print is actually a special statement and not a function*.

This is also why it can't be used like: lambda x: print x

Note that (expr) does not create a Tuple (it results in expr), but , does. This likely results in the confusion between print (x) and print (x, y) in Python 2.7

(1)   # 1 -- no tuple Mister!
(1,)  # (1,)
(1,2) # (1, 2)
1,2   # 1 2 -- no tuple and no parenthesis :) [See below for print caveat.]

However, since print is a special syntax statement/grammar construct in Python 2.x then, without the parenthesis, it treats the ,'s in a special manner - and does not create a Tuple. This special treatment of the print statement enables it to act differently if there is a trailing , or not.

Happy coding.


*This print behavior in Python 2 can be changed to that of Python 3:

from __future__ import print_function

Solution 2

It's all very simple and has nothing to do with forward or backward compatibility.

The general form for the print statement in all Python versions before version 3 is:

print expr1, expr2, ... exprn

(Each expression in turn is evaluated, converted to a string and displayed with a space between them.)

But remember that putting parentheses around an expression is still the same expression.

So you can also write this as:

print (expr1), (expr2), ... (expr3)

This has nothing to do with calling a function.

Solution 3

Here we have interesting side effect when it comes to UTF-8.

>> greek = dict( dog="σκύλος", cat="γάτα" )
>> print greek['dog'], greek['cat']
σκύλος γάτα
>> print (greek['dog'], greek['cat'])
('\xcf\x83\xce\xba\xcf\x8d\xce\xbb\xce\xbf\xcf\x82', '\xce\xb3\xce\xac\xcf\x84\xce\xb1')

The last print is tuple with hexadecimal byte values.

Solution 4

Basically in Python before Python 3, print was a special statement that printed all the strings if got as arguments. So print "foo","bar" simply meant "print 'foo' followed by 'bar'". The problem with that was it was tempting to act as if print were a function, and the Python grammar is ambiguous on that, since (a,b) is a tuple containing a and b but foo(a,b) is a call to a function of two arguments.

So they made the incompatible change for 3 to make programs less ambiguous and more regular.

(Actually, I think 2.7 behaves as 2.6 did on this, but I'm not certain.)

Share:
92,860

Related videos on Youtube

Hubro
Author by

Hubro

Code enthusiast!

Updated on March 01, 2020

Comments

  • Hubro
    Hubro about 4 years

    In Python 2.7 both the following will do the same

    print("Hello, World!") # Prints "Hello, World!"
    
    print "Hello, World!" # Prints "Hello, World!"
    

    However the following will not

    print("Hello,", "World!") # Prints the tuple: ("Hello,", "World!")
    
    print "Hello,", "World!" # Prints the words "Hello, World!"
    

    In Python 3.x parenthesis on print is mandatory, essentially making it a function, but in 2.7 both will work with differing results. What else should I know about print in Python 2.7?

    • Admin
      Admin almost 13 years
      In Python 2.x print is actually a special statement, not a function. This is also why it can't be used like: lambda x: print x Note that (expr) does not create a Tuple (it results in expr), but , does.
    • GWW
      GWW almost 13 years
      I'm assuming the support for print as a function and print as a statement is to maintain backwards compatibility with older versions of python while encouraging people to use the new syntax to migrate towards python 3.
    • Jeff Mercado
      Jeff Mercado almost 13 years
      p.s., To enable the print function in 2.7 (and not have the print statement behavior), you have to do a future import: from __future__ import print_function
    • kapad
      kapad over 4 years
      Will the second example will in fact print "Hello,World!" (without the space) or will it print "Hello, World!" (with the space) as in the example.
  • Hubro
    Hubro almost 13 years
    Thanks for the (expr) != tuple explanation :-)
  • Lennart Regebro
    Lennart Regebro almost 13 years
    No it wasn't "tempting" to use it as a function. :) However, it was impossible to use it as a function, so you can't do [print x for x in alist] for example.
  • Hubro
    Hubro almost 12 years
    I assume that's because print prints UTF-8 correctly, but when it receives a tuple, like your last print, it runs repr on it, at which point it probably encodes all strings in the dict to ASCII.
  • Karlo Smid
    Karlo Smid almost 12 years
    @Codemonkey, you are right about repr. You are wrong about ASCII. ASCII is default encoding for Python. But I have at the beginning of Python script #encoding=utf-8, linux env LANG=en_US.UTF-8. So repr encodes not using default ASCII, but utf-8 encoding.
  • Ishbir
    Ishbir over 9 years
    Repr encodes str with the special string_escape encoding. The string was already unicode encoded as UTF-8.
  • Hubro
    Hubro over 9 years
    @KarloSmid: What I meant to say was that repr probably takes steps to ensure that the text can be represented by ASCII (by means of escaping non-ASCII symbols), not necessarily that the string is encoded as ASCII. I still don't know if that's completely accurate though.
  • Martijn Pieters
    Martijn Pieters about 7 years
    All Python containers (list, dict, tuple, set) include their contents as repr() output when converted to a string (they don't implement __str__, only __repr__). What you see is not special to UTF-8; the repr() of a string gives you valid Python string literals that are ASCII-safe.
  • Martijn Pieters
    Martijn Pieters about 7 years
    This is a perfectly correct answer, I'm not sure why it was downvoted so much either.
  • vinnief
    vinnief over 6 years
    It's not about print (expr1), (expr2), ... (expr3), it is about why print (expr1, expr2, ... , expr3) is legal in python 2.x while it shouldn't be according to 2.x standards.
  • Peter Mortensen
    Peter Mortensen almost 6 years
    Does this depend on whether it is UTF-8, UTF-16, or UTF-32?