Old Man Yells At Cloud
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Wed Sep 20 02:01:12 EDT 2017
On Tue, 19 Sep 2017 18:43:43 -0700, Rick Johnson wrote:
> On Tuesday, September 19, 2017 at 12:55:14 PM UTC-5, Chris Angelico
> wrote:
>> On Wed, Sep 20, 2017 at 3:44 AM, Stefan Ram <ram at zedat.fu-berlin.de>
>> wrote:
>> > Steve D'Aprano <steve+python at pearwood.info> did *not* write [it was
>> > edited/abbreviated by me - S. R.]:
>> > |disadvantages:
>> > |0 - it makes print a special thing
>
> No more "special" than any other reserved word in Python.
The other reserved words are either:
- values, like None, which can be included in expressions;
- operators, like `is`, `or`, and `not`;
- block statements, like `for x in seq` or `while flag` which
require a block;
- statements, like `import` and `del`, which operate on names
rather than values.
(Did I miss any?)
print is the only one which could be a function, and looks like a
function (apart from the lack of parens). Hence people keep trying to do
things like use it in lambdas:
https://www.quora.com/Why-does-putting-print-inside-a-Python-lambda-
function-raise-a-syntax-error
Since it *could* be a function, but isn't, that makes it special in a
special way.
>> > |1 - beginners have to unlearn
>
> Only if they decide to move to Python3 *AND* only if they decide to use
> the print function at _all_.
Even if you don't use print, you will still have to read other people's
code that uses it.
And its not just a Python 3 issue. Long before there was a Python 3,
people would over-generalise from function calls and add extraneous
brackets around print's argument. It wouldn't matter if you were printing
a single value, but if you printed two arguments, you would actually
print a tuple instead.
Here are some more recent examples:
https://stackoverflow.com/questions/38254008/
https://stackoverflow.com/questions/36345800/
but if you have plenty of time on your hands to search the archives of
this mailing list (newsgroup) you'll find people occasionally writing
"print(...)" all the way back to Python 2.0 or 1.5.
Very possibly including me.
>> > |2 - `print(x, y)` is *not* the same as `print x, y`;
>
> Well, duh!
Duh to *you and me*, perhaps, but not so obvious to everyone. See links
above.
And especially not obvious to beginners, who have to learn that print is
magically and unlike all other functions, doesn't require parentheses.
[...]
> I'll leave the remaining feature implementations as an exercise for the
> reader...
I already said that you can work around the crippling limitations of
print by avoiding it.
So why have a standard print (pseudo-)function if it is so crippled and
limited that it has to be worked around to be useful for anything more
complicated than "Hello World"?
For the microscopic cost of requiring parens when calling the print
function, you gain all the features of a function. That's a great
tradeoff. Beginners have to learn to use parens for every other function
they use. Having one more is an insignificant cost. And for advanced
programmers, now you have a print function that is actually useful.
>> > |5 - it can't be mocked, shadowed, monkey-patched or replaced for
>> > testing;
>
> So wrap sys.stdout.write with your own function and then mock it until
> it crys and runs home to mommy; shadow it until it reports you as a
> stalker; and monkey patch it until your sewing hand becomes racked with
> arthritic pain!
You aren't thinking it through far enough.
If it's *my* code, I can just use my editor to search for "print foo" and
replace it with "awesome_print(foo)" and I'm done.
But if I'm using a library or some other piece of code that uses print,
and I can't edit the source code (maybe I don't even have the source
code), I need to mock it (etc). Now I'm completely out of luck, because
you can't shadow or replace the print statement.
I *might* be able to hack up some sort of magic replacement for stdout,
but that's easier said than done, and if the library is printing to other
files I'm screwed. What am I going to do, chase down every single call to
print? How? By scanning the .pyc files and disassembling the byte-code?
Sure, if you are willing to invest sufficiently large time, money and
effort, there's a solution. But something which should take literally
five seconds:
import nasty_library_that_uses_print as nasty
nasty.print = lambda *args: logger(*args) # or similar
could take weeks of development effort to get right.
>> > |6 - and you can't even write help(print) in the interactive
>> > interpreter
>
> Hmm, neither can you get help for these:
>
> # PYTHON 2.x
> >>> help(del)
> SyntaxError: invalid syntax
Indeed you can't.
But there is a very good reason why del, if, else etc are statements.
They *have to be*. For example, you can't write del as a function,
because if you do, it won't receive the names of the variables, only
their values.
It's a trade-off. With del, if, else etc, the value of them being
statements far outweighs the disadvantages. But for print, its the other
way around.
As I've said, apart from saving *one* character (okay, if it makes Rick
feel better, two keystrokes on a QWERTY keyboard), what actual concrete,
positive benefit is there in making print a statement?
If print had always been a function, what arguments are there for making
it a statement?
--
Steven D'Aprano
“You are deluded if you think software engineers who can't write
operating systems or applications without security holes, can write
virtualization layers without security holes.” —Theo de Raadt
More information about the Python-list
mailing list