问题
I searched around and couldn't find an answer to this either on this site or elsewhere (always a challenge searching for topics involving punctuation chars).
I was looking up the StringIO
in the Python standard library (here) and one of the examples is this (excerpt):
import StringIO
output = StringIO.StringIO()
output.write('First line.\n')
print >>output, 'Second line.' # <-- This is the line I'm asking about
How or why does the >>
operator work here? As far as I can tell (and I'm no Python expert), this is the right shift operator. I thought perhaps StringIO
overrides __rshift__
or something, but the source for StringIO does not betray any such thing.
I haven't poked around to see how the print
built-in is implemented yet, but with initial searching I'm unable to figure out how this works. Anyone?
回答1:
This is really a few questions in one.
First, the "how" question:
The >>
token is not actually an operator here; it's part of the syntax of the print
statement, as documented here. The grammar is:
print_stmt ::= "print" ([expression ("," expression)* [","]]
| ">>" expression [("," expression)+ [","]])
… and the semantics are:
This form is sometimes referred to as “print chevron.” In this form, the first expression after the
>>
must evaluate to a “file-like” object, specifically an object that has awrite()
method as described above. With this extended form, the subsequent expressions are printed to this file object.
Second, the "why" question:
Early on, the Python developers thought this was a convenient way to write to files.
Since then, they've added stdout redirection, and more powerful file and string-formatting APIs, so it's not as useful anymore. And, thanks to other modern features like keyword arguments, and a few decades to think about it, they've come up with a more flexible way to design print as a regular function that doesn't require any special syntax at all. But removing it would break backward compatibility, so it couldn't be removed until 3.0.
And it was removed in 3.0; you're only still seeing it because you're using an older version.
If you want the new print
function in 2.7, however, you can use a future statement: from __future__ import print_function
. But that will of course break print >>foo, spam
; you'll have to rewrite it as print(spam, file=foo)
.
回答2:
In Python 2, print
is a statement (not a function), and statements can make up any goofy syntax they like ;-) The >>
here has nothing to do with the right shift operator - it's a gimmick specific to the print
statement.
This is widely viewed as ugly, and in Python 3 print
is a builtin function (instead of a statement), and to specify a file to which to print Python 3 adds an optional file=
argument to the print()
function.
回答3:
It is additional syntax; the compiler looks for >>
after a print
statement:
>>> import dis
>>> def print_redirected(fh, msg):
... print >>fh, msg
...
>>> dis.dis(print_redirected)
2 0 LOAD_FAST 0 (fh)
3 DUP_TOP
4 LOAD_FAST 1 (msg)
7 ROT_TWO
8 PRINT_ITEM_TO
9 PRINT_NEWLINE_TO
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>> def print_direct(msg):
... print msg
...
>>> dis.dis(print_direct)
2 0 LOAD_FAST 0 (msg)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
The >>
results in different bytecode; PRINT_ITEM_TO
instead of PRINT_ITEM
.
This is the result of the Python grammar explicitly allowing for the extended syntax:
print_stmt: 'print' ( [ test (',' test)* [','] ] |
'>>' test [ (',' test)+ [','] ] )
At no point does the compiler interpret the >>
as a right-shift operator.
Redirecting print output with this syntax is little used; you can just write directly to the file, or reassign to sys.stdout instead. The simple formatting options the print
statement offers can easily be replicated using (much more powerful) string formatting in any case.
Python 3's print() function accepts a file
keyword argument to achieve the same functionality.
回答4:
Your question is answered in a duplicate post. Quoted:
print also has an extended form, defined by the second portion of the syntax described above. This form is sometimes referred to as “print chevron.” In this form, the first expression after the >> must evaluate to a “file-like” object, specifically an object that has a write() method as described above. With this extended form, the subsequent expressions are printed to this file object. If the first expression evaluates to None, then sys.stdout is used as the file for output.
来源:https://stackoverflow.com/questions/18837408/why-how-does-pythons-print-built-in-allow-the-operator