Search code examples
pythonpep8

Multiline If statement with a single conditional


Lets say I have two variables

self.SuperLongSpecificCorperateVariableNameIcantChangeCommunication 

and

self.SuperLongSpecificCorperateVariableNameIcantChangeControl 

And I need to compare them.

The issue being that, when I put them both in an if statement, it blows past the style checker's line length.

if (self.SuperLongSpecificCorperateVariableNameIcantChangeCommunication != self.SuperLongSpecificCorperateVariableNameIcantChangeControl):

The way around this would be to split this into two lines.

if (self.SuperLongSpecificCorperateVariableNameIcantChangeCommunication \
    != self.SuperLongSpecificCorperateVariableNameIcantChangeControl):

My coworkers are split on whether PEP 8 has you split between conditionals or whether you can split up a conditional itself. Ideally we would get approval to change the variable name, but in the meantime, what does PEP 8 say we should do in this case?


Solution

  • Firstly, PEP 8 says you can split long lines under Maximum Line Length:

    Long lines can be broken over multiple lines by wrapping expressions in parentheses. These should be used in preference to using a backslash for line continuation.

    In fact, the backslash in your example is not needed because of the parentheses.


    PEP 8 says you can split a conditional under multiline if-statements, although the main focus of that section is how to distinguish it from the following block.

    When the conditional part of an if-statement is long enough to require that it be written across multiple lines, it's worth noting that the combination of a two character keyword (i.e. if), plus a single space, plus an opening parenthesis creates a natural 4-space indent for the subsequent lines of the multiline conditional. This can produce a visual conflict with the indented suite of code nested inside the if-statement, which would also naturally be indented to 4 spaces. This PEP takes no explicit position on how (or whether) to further visually distinguish such conditional lines from the nested suite inside the if-statement. Acceptable options in this situation include, but are not limited to:

    # No extra indentation.
    if (this_is_one_thing and
        that_is_another_thing):
        do_something()
    
    # Add a comment, which will provide some distinction in editors
    # supporting syntax highlighting.
    if (this_is_one_thing and
        that_is_another_thing):
        # Since both conditions are true, we can frobnicate.
        do_something()
    
    # Add some extra indentation on the conditional continuation line.
    if (this_is_one_thing
            and that_is_another_thing):
        do_something()
    

    Personally, I would go for the last option for maximum readability. So that gives us:

    if (self.SuperLongSpecificCorperateVariableNameIcantChangeCommunication
            != self.SuperLongSpecificCorperateVariableNameIcantChangeControl):
        do_something()
    

    Other options

    You could use temporary "internal use" names to shorten the line:

    _Comm = self.SuperLongSpecificCorperateVariableNameIcantChangeCommunication
    _Control = self.SuperLongSpecificCorperateVariableNameIcantChangeControl
    if _Comm != _Control:
        do_something()
    

    This is assuming the context is not in a local scope. If it is actually in a local scope, they don't need to be "internal use".


    You could use a helper function to give them shorter names in a local scope. Since they're attributes, you can pass in their object:

    def _compare(instance):
        a = instance.SuperLongSpecificCorperateVariableNameIcantChangeCommunication
        b = instance.SuperLongSpecificCorperateVariableNameIcantChangeControl
        return a != b
    
    if _compare(self):
        do_something()