What is the proper level of indent for hanging indent with type hinting in python?
<p>What is the proper syntax for a hanging indent for a method with multiple parameters and type hinting?</p>

<p><strong>Align under first parameter</strong></p>

<pre><code>def get_library_book(self,
                     book_id: str,
                     library_id: str
                     )-&gt; Book:
</code></pre>

<p><strong>Indent one level beneath</strong></p>

<pre><code>def get_library_book(
    self, 
    book_id: str, 
    library_id: str
) -&gt; Book:
</code></pre>

<p>PEP8 supports the <em>Indent one level beneath</em> case, but does not specify if <em>Align under first parameter</em> is allowed. It states: </p>

<blockquote>
  <p>When using a hanging indent the following should be considered; there
  should be no arguments on the first line and further indentation
  should be used to clearly distinguish itself as a continuation line.</p>
</blockquote>

<p>PEP8 has many good ideas in it, but I wouldn't rely on it to decide this kind of question about whitespace. When I studied PEP8's recommendations on whitespace, I found them to be inconsistent and even contradictory.</p>

<p>Instead, I would look at general principles that apply to nearly all programming languages, not just Python.</p>

<p>The column alignment shown in the first example has many disadvantages, and I don't use or allow it in any of my projects.</p>

<p>Some of the disadvantages:</p>

<ul>
<li>If you change the function name so its length is different, you must realign all of the parameters.</li>
<li>When you do that realignment, your source control diffs are cluttered with unnecessary whitespace changes.</li>
<li>As the code is updated and maintained, it's likely that you'll miss some of the alignment when renaming variables, leading to misaligned code.</li>
<li>You get much longer line lengths.</li>
<li>The alignment doesn't work in a proportional font. (Yes, some developers prefer proportional fonts, and if you avoid column alignment, your code will be equally readable in monospaced or proportional fonts.)</li>
</ul>

<p>It gets even worse if you use column alignment in more complex cases. Consider this example:</p>

<pre><code>let mut rewrites = try_opt!(subexpr_list.iter()
                                        .rev()
                                        .map(|e| {
                                            rewrite_chain_expr(e,
                                                               total_span,
                                                               context,
                                                               max_width,
                                                               indent)
                                        })
                                        .collect::&lt;Option&lt;Vec&lt;_&gt;&gt;&gt;());
</code></pre>

<p>This is Rust code from the Servo browser, whose coding style mandates this kind of column alignment. While it isn't Python code, exactly the same principles apply in Python or nearly any language.</p>

<p>It should be apparent in this code sample how the use of column alignment leads to a bad situation. What if you needed to call another function, or had a longer variable name, inside that nested <code>rewrite_chain_expr</code> call? You're just about out of room unless you want <em>very</em> long lines.</p>

<p>Compare the above with either of these versions which use a purely indentation-based style like your second Python example:</p>

<pre><code>let mut rewrites = try_opt!(
    subexpr_list
        .iter()
        .rev()
        .map( |e| {
            rewrite_chain_expr( e, total_span, context, max_width, indent )
        })
        .collect::&lt;Option&lt;Vec&lt;_&gt;&gt;&gt;()
);
</code></pre>

<p>Or, if the parameters to <code>rewrite_chain_expr</code> were longer or if you just wanted shorter lines:</p>

<pre><code>let mut rewrites = try_opt!(
    subexpr_list
        .iter()
        .rev()
        .map( |e| {
            rewrite_chain_expr(
                e,
                total_span,
                context,
                max_width,
                indent
            )
        })
        .collect::&lt;Option&lt;Vec&lt;_&gt;&gt;&gt;()
);
</code></pre>

<p>In contrast to the column-aligned style, this pure indentation style has many advantages and no disadvantages at all.</p>

python python-3.x pep8 type-hinting