Python multi-line comments and triple-quoted strings

This morning Twitter suggested to me that I might be interested in this tweet and Twitter was right (for once)!

I was pretty sure that PEP 8 was the last word on block comments and told Bill so.

Then while eating lunch I stumbled onto this tweet by a Python programmer with some cred.

I'm inclined to believe the author of Python, but I decided to check. It's been a long time since I dug into Python bytecode and I thought I could use a refresher. Here's a small program that contains a script in a triple-quoted string. It compiles the script to bytecode and then uses dis, the Python disassembler, to show the instructions in the script's bytecode. I've never done dis before!

import dis

source = '''
"""script.py:

A script."""

text = """
Some
multi-line
text.
"""

"""
Unused multi-line text
generates
no code.
"""

"""
But if you
use it...
""" + " code!"

print(text)
'''

code = compile(source, '<string>', 'exec')
print(dis.dis(code))

The first anonymous string is stored as the module's __doc__ (this goes for functions, classes, and methods as well). The unused anonymous string beginning with "Unused" does't make it into the bytecode, confirming Guido Van Rossum's tweet. The anonymous string beginning with "But" that is used in the string concatenation does make it into the bytecode.

$ python3.6 script.py
  5           0 LOAD_CONST               0 ('script.py:\n\nA script.\n')
              2 STORE_NAME               0 (__doc__)

 11           4 LOAD_CONST               1 ('\nSome\nmulti-line\ntext.\n')
              6 STORE_NAME               1 (text)

 22           8 LOAD_CONST               2 ('\nBut if you\nuse it...\n')
             10 LOAD_CONST               3 (' code!')
             12 BINARY_ADD
             14 POP_TOP

 24          16 LOAD_NAME                2 (print)
             18 LOAD_NAME                1 (text)
             20 CALL_FUNCTION            1
             22 POP_TOP
             24 LOAD_CONST               4 (None)
             26 RETURN_VALUE
None

I didn't know that unused anonymous strings were ignored like this. I assumed they hung around briefly until garbage collection got them, but Python optimizes them away. Note: you can even optimize the __doc__ away with python -OO.

There are limits to this kind of block comment. They can't be used within brackets, for one thing.

Myself, I'm going to stick to # and Vim block-mode selection, but I'm going to stop telling people using triple-quoted strings as block comments that they're flat wrong.