Why does python allow an empty function (with doc-string) body without a "pass" statement?
Question: 
    class SomeThing(object):
        """Represents something"""
    
        def method_one(self):
            """This is the first method, will do something useful one day"""
    
        def method_two(self, a, b):
            """Returns the sum of a and b"""
            return a + b
    

In a recent review of some code similar to the above, a colleague asked:

> How come `method_one` is successfully parsed and accepted by python? Doesn't
> an empty function need a body consisting of just
> [`pass`](http://docs.python.org/2/reference/simple_stmts.html#pass)? i.e.
> shouldn't it look like this?
    
    
    def method_one(self):
        """This is the first method, will do something useful one day"""
        pass
    

My response at the time was something like:

> Although the docstring is usually not considered to be part of the function
> body, because it is not "executed", it is parsed as such, so the `pass` can
> be omitted.

In the spirit of [sharing knowledge Q&A
style](http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-
own-questions/), I thought I'd post the more rigorous answer here.


Answer: According to the [Python 2.7.5 grammar
specification](http://docs.python.org/2/reference/grammar.html), which is read
by the parser generator and used to parse Python source files, a function
looks like this:

    
    
    funcdef: 'def' NAME parameters ':' suite
    

The function body is a `suite` which looks like this

    
    
    suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
    

Following this all the way through the grammar, `stmt` can be an `expr_stmt`,
which can be just a `testlist`, which can be just a single `test` which can
(eventually) be just an `atom`, which can be just a single `STRING`. The
docstring.

Here are just the appropriate parts of the grammar, in the right order to
follow through:

    
    
    stmt: simple_stmt | compound_stmt
    simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
    small_stmt: (expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt |
                 import_stmt | global_stmt | exec_stmt | assert_stmt)
    expr_stmt: testlist (augassign (yield_expr|testlist) |
                         ('=' (yield_expr|testlist))*)
    testlist: test (',' test)* [',']
    test: or_test ['if' or_test 'else' test] | lambdef
    or_test: and_test ('or' and_test)*
    and_test: not_test ('and' not_test)*
    not_test: 'not' not_test | comparison
    comparison: expr (comp_op expr)*
    comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
    expr: xor_expr ('|' xor_expr)*
    xor_expr: and_expr ('^' and_expr)*
    and_expr: shift_expr ('&' shift_expr)*
    shift_expr: arith_expr (('<<'|'>>') arith_expr)*
    arith_expr: term (('+'|'-') term)*
    term: factor (('*'|'/'|'%'|'//') factor)*
    factor: ('+'|'-'|'~') factor | power
    power: atom trailer* ['**' factor]
    atom: ('(' [yield_expr|testlist_comp] ')' |
           '[' [listmaker] ']' |
           '{' [dictorsetmaker] '}' |
           '`' testlist1 '`' |
           NAME | NUMBER | STRING+)
    

