9

I stumbled upon an interesting and unexpected feature of Python:

def fun():
    """Foo’s docstring"""

is a valid function? According to PEP 257, “A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition” meaning that the docstring itself is considered a statement?

I would have expected that at least a pass statement is required here. The above example contradicts the Python Zen of “explicit is better than implicit” as pass states an explicit intent, and a docstring does not.

Can anybody shed some light on the intent?

Jens
  • 8,423
  • 9
  • 58
  • 78
  • 9
    What's unclear? As that quote tells you, the string is the first statement, only one statement is required by [the grammar](https://docs.python.org/3/reference/grammar.html) for the function to be syntactically valid. That's *not* an empty function, in other words. – jonrsharpe Sep 10 '17 at 22:16
  • 1
    What exactly do you mean by 'intent'? – pvg Sep 10 '17 at 22:17
  • I’ve extended the question... – Jens Sep 10 '17 at 22:19
  • 9
    The Zen of Python doesn't tell you about the grammar. If you think a `pass` statement after the docstring makes the code clearer in intent then by all means add one, but it isn't *required* for the code to run. It would only complicate the parser to have the requirement that `suite` contains at least one statement, except in the case that it's in a `funcdef` and that first statement is a string literal, in which case it must contain at least two. *"Simple is better than complex."* – jonrsharpe Sep 10 '17 at 22:20
  • Yes, the Python parser does allow you to do some things that violate the Zen of Python, but so what? What exactly is your question? – jwodder Sep 10 '17 at 22:25
  • @jonrsharpe: I understand that. I just find it odd/surprising that a _string literal_ is also considered a _statement_ when placed in a certain location, and as a consequence allows an empty function like the one above that, to me, conflicts with other required uses of `pass`. – Jens Sep 10 '17 at 22:26
  • 2
    What do you mean *"considered a statement when placed in a certain location"*? A string literal on its own is an expression, thus an expression statement. The fact that this is *also* special-cased as a docstring when such a statement is the first in a function/class/module/method doesn't change that. – jonrsharpe Sep 10 '17 at 22:35

1 Answers1

12

A string literal is just like any other literal. It also works if you just put in an integer:

def func():
    1

However, it doesn't work if you only use a comment:

def func():
    # test

# IndentationError: expected an indented block

Even though it's also added as docstring (saved in the __doc__ attribute) it's also a function level constant:

def func():
    """I'm a function"""

>>> func.__code__.co_consts
("I'm a function", None)

So the presence of a string literal as only content of a function doesn't change how the function is actually "parsed" and "compiled" itself. Well, apart from the fact that it also got a not-None __doc__ attribute.

It's actually very handy for abstractmethods (see for example "Body of abstract method in Python"), where you don't need an actual function body.

MSeifert
  • 145,886
  • 38
  • 333
  • 352