72

I've heard several times that print being a function (3.x) is better than it being a statement (2.x). But why?

I was a fan of it being a statement mainly because it allowed me to type two less characters (ie, the parentheses).

I'd be interested to see some situations where the print statement just doesn't cut it, and a function is superior.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
rectangletangle
  • 50,393
  • 94
  • 205
  • 275
  • 7
    @LennartRegebro: It’s not just two characters: the whole flow feels different. Not having it as statement incurs a cost - especially for those used to the statement. But it relieves quite some pains in corner cases. – Arne Babenhauserheide Jul 24 '12 at 13:33
  • 2
    Yeah, now you have to track extra parentheses, making concatenating many strings slightly more annoying if you're also embedding in-line string replacements with tuples. I'm definitely getting more typos/invalid syntax erros in Py3 because of this! It's caused me to now use a variable to generate the printed text. – Demis Jan 30 '16 at 01:33

5 Answers5

58

Rationale

The print statement has long appeared on lists of dubious language features that are to be removed in Python 3000, such as Guido's "Python Regrets" presentation [1]. As such, the objective of this PEP is not new, though it might become much disputed among Python developers.

The following arguments for a print() function are distilled from a python-3000 message by Guido himself [2]:

  • print is the only application-level functionality that has a statement dedicated to it. Within Python's world, syntax is generally used as a last resort, when something can't be done without help from the compiler. Print doesn't qualify for such an exception.
  • At some point in application development one quite often feels the need to replace print output by something more sophisticated, like logging calls or calls into some other I/O library. With a print() function, this is a straightforward string replacement, today it is a mess adding all those parentheses and possibly converting >>stream style syntax.
  • Having special syntax for print puts up a much larger barrier for evolution, e.g. a hypothetical new printf() function is not too far fetched when it will coexist with a print() function.
  • There's no easy way to convert print statements into another call if one needs a different separator, not spaces, or none at all. Also, there's no easy way at all to conveniently print objects with some other separator than a space.
  • If print() is a function, it would be much easier to replace it within one module (just def print(*args):...) or even throughout a program (e.g. by putting a different function in __builtin__.print). As it is, one can do this by writing a class with a write() method and assigning that to sys.stdout – that's not bad, but definitely a much larger conceptual leap, and it works at a different level than print.

PEP 3105 – Make print a function

Community
  • 1
  • 1
Jochen Ritzel
  • 104,512
  • 31
  • 200
  • 194
  • 1
    Nice, but doesn't address why an *expression* (function-call) can be easier to deal with than a *statement* in terms of grammar constructs, most notably a simple `lambda`. –  Jun 04 '11 at 23:10
44

Everything from Jochen's answer and Sven's answer, plus:

You can use print() it in places where you can't use print, such as:

[print(x) for x in range(10)]
MultiplyByZer0
  • 6,302
  • 3
  • 32
  • 48
Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
  • 14
    I intentionally did not mention this one, since I could not think of any use which I would recommend using `print()` as an expression rather than a statement for. Your example creates an unneeded list of 10 times the values `None`, and it would be certainly better to use `for x in range(10): print(x)`. – Sven Marnach Jun 05 '11 at 11:07
  • 8
    @Sven: Sure. I certainly didn't intend it to be the accepted answer. :) – Lennart Regebro Jun 05 '11 at 11:48
  • 2
    I just tried to use a print in a lambda, where a class was allowing me to pass a function to log values with. I wanted to just print them out. I had to define a function elsewhere because you can't write `lambda x: print x` :(. – Daniel Buckmaster Oct 08 '14 at 08:18
  • It also made it easier for the smart people who build the language Python to add such functionality as a different separator – Ofer Rahat Oct 18 '17 at 07:41
37

One advantage of print being a function is consistency. There is no reason for it to be a statement. Compare these two lines

2.x: print >> my_file, x
3.x: print(x, file=my_file)

The new version looks much more like Python, doesn't it?

Another advantage of the function version is flexibility. For example, if you want to catch all print calls for debugging purposes, you can now simply redefine print:

def print(*args, **kwargs):
    # whatever
    __builtins__.print(*args, **kwargs)
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • 3
    re “The new version looks much more like Python, doesn't it?”: they're both valid Python, aren't they? I believe you meant “pythonic”, but even “pythonic” is quite vague. I don't disagree with your answer, I just find your question to be an insufficient argument for the `print` function. (Delegation of the answer to the OP is for psychologists and managers, I think :) – tzot Jun 05 '11 at 00:33
  • 3
    ΤΖΩΤΖΙΟΥ: I said it's about consistency. This is not a hard fact, so I have to leave the judgement ultimately to the reader. I could make it "In my opinion, the new version looks more like Python" if you prefer. :) – Sven Marnach Jun 05 '11 at 00:55
18

I thought over this question and had no idea about pros of python 3 version. But when I needed to print the columns of pandas.DataFrame (without Index([...])), I've found out that

print *df.columns

throws an exception, while

print(*df.columns)

works fine! And if you want to have same (configurable) print options in several call prints, you can save them to dictionary and pass as **print_options

So at least *args, **kw_args tricks are a good reason for print to be a function!

Alleo
  • 7,891
  • 2
  • 40
  • 30
12

You can replace the built-in print by a custom one:

import os
import sys

def print(s):
   sys.stderr.write('Will now print ' + str(s) + '.' + os.linesep)
   sys.stdout.write(str(s) + os.linesep)

print(['A', 'list'])
# Output: 
# stderr: Will now print ['A', 'list'].
# stdout: ['A', 'list']

You can use print inside a lambda or a function call etc.:

example_timeout_function(call=lambda: print('Hello world'), timeout=5)
do_things(print_function=print)
Artur Gaspar
  • 4,407
  • 1
  • 26
  • 28