Python Forum

Full Version: Python Dev suggestion: Combining line-wrap with comments inside functions
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
(EDIT: I messed up the title. "inside functions" should not be there. The suggestion is more general than that.)

Code Case
Sometimes, I have an expression in a function, whose multiple parts I want to comment on separately. In order to do so, I combine comments with line wrapping. The following piece of code illustrates what I mean and, in python 3.8.3 on windows 10, it trows an error.
import numpy as np

#reflects escaping particles off of a wall
#pos(ition) & velo(city) are Nx3 numpy arrays with N the number of particles,
def reflect(pos, velo, llimit, rlimit, boxmomentum, N):
    lmask = pos <= llimit
    rmask = pos >= rlimit
    pos = pos                  # do nothing when not crossing a wall
        + 2*rmask*(llimit-pos) # reflect when crossing left,aft&lower walls
        - 2*lmask*(rlimit-pos) # reflect when crossing right,fore&upper walls
    print("Success")
    return pos, velo, boxmomentum
Error:
File "C:\Users\This_is_private_and_thus_redacted\some_python_program.py", line 9 + 2*rmask*(llimit-pos) # reflect when crossing left,aft&lower walls ^ IndentationError: unexpected indent [Finished in 0.134s]
I've found that there are two ways to change make this code work:

Solution 1) Not have that indentation
After all, this is what the error message reports. Such a code looks like this
import numpy as np

#reflects escaping particles off of a wall
#pos(ition) & velo(city) are Nx3 numpy arrays with N the number of particles,
def reflect(pos, velo, llimit, rlimit, boxmomentum, N):
    lmask = pos <= llimit
    rmask = pos >= rlimit
    pos = pos              # do nothing when not crossing a wall
    + 2*rmask*(llimit-pos) # reflect when crossing left,aft&lower walls
    - 2*lmask*(rlimit-pos) # reflect when crossing right,fore&upper walls
    print("Success")
    return pos, velo, boxmomentum
Output:
Success [Finished in 1.04s]
However, in the spirit of the Python Style Guide: Code Layout: Indentation and Should a Line Break Before or After a Binary Operator?, I would like to have the extra indent, since that is what they are doing there as well. Luckily, there is another way:

Solution 2)Backslash wrapping and ditching comments
This piece of code, which uses backslash-wrapping, will also work fine

import numpy as np

#reflects escaping particles off of a wall
#pos(ition) & velo(city) are Nx3 numpy arrays with N the number of particles,
def reflect(pos, velo, llimit, rlimit, boxmomentum, N):
    lmask = pos <= llimit
    rmask = pos >= rlimit
    pos = pos \
        + 2*rmask*(llimit-pos) \
        - 2*lmask*(rlimit-pos)
    print("Success")
    return pos, velo, boxmomentum
Output:
Success [Finished in 1.117ss]
Sweet, so we just need to explicitly tell python that lines were wrapped and indentation means nothing. Now it is just a case of adding the comments back in.
import numpy as np

#reflects escaping particles off of a wall
#pos(ition) & velo(city) are Nx3 numpy arrays with N the number of particles,
def reflect(pos, velo, llimit, rlimit, boxmomentum, N):
    lmask = pos <= llimit
    rmask = pos >= rlimit
    pos = pos \                  # do nothing when not crossing a wall
        + 2*rmask*(llimit-pos) \ # reflect when crossing left,aft&lower walls
        - 2*lmask*(rlimit-pos)   # reflect when crossing right,fore&upper walls
    print("Success")
    return pos, velo, boxmomentum
Error:
File "C:\Users\This_is_private_and_thus_redacted\some_python_program.py", line 8 pos = pos \ # do nothing when not crossing a wall ^ SyntaxError: unexpected character after line continuation character [Finished in 0.138s]
Awww Sad . It does not work.

Extra notes
I tried two other things. First: doing no indents and backslashes and comments
import numpy as np

#reflects escaping particles off of a wall
#pos(ition) & velo(city) are Nx3 numpy arrays with N the number of particles,
def reflect(pos, velo, llimit, rlimit, boxmomentum, N):
    lmask = pos <= llimit
    rmask = pos >= rlimit
    pos = pos \             # do nothing when not crossing a wall
    + 2*rmask*(llimit-pos)\ # reflect when crossing left,aft&lower walls
    - 2*lmask*(rlimit-pos)  # reflect when crossing right,fore&upper walls
    print("Success")
    return pos, velo, boxmomentum
Error:
File "C:\Users\This_is_private_and_thus_redacted\some_python_program.py", line 8 pos = pos \ # do nothing when not crossing a wall ^ SyntaxError: unexpected character after line continuation character [Finished in 0.14s]
Secondly, I tried to verify that this behaviour happens regardless of whether the code sits in a function already. This is the case, as you can test by uncommenting portions from this code:
import numpy as np

N = 1000 #amount of particles
L = 1000 #length of box
llimit = 0
rlimit = L
pos = np.random.rand(*(N,3))
lmask = pos <= llimit
rmask = pos >= rlimit

'''
# comments and indents = unexpected indent
pos = pos                  # do nothing when not crossing a wall
    + 2*rmask*(llimit-pos) # reflect when crossing left,aft&lower walls
    - 2*lmask*(rlimit-pos) # reflect when crossing right,fore&upper walls
print("Success")
'''

'''
#comments, no indents = success
pos = pos              # do nothing when not crossing a wall
+ 2*rmask*(llimit-pos) # reflect when crossing left,aft&lower walls
- 2*lmask*(rlimit-pos) # reflect when crossing right,fore&upper walls
print("Success")
'''

'''
#indents, backslash = success
pos = pos \
    + 2*rmask*(llimit-pos) \
    - 2*lmask*(rlimit-pos)
print("Success")
'''

'''
#indents, backslash, comments = unexpected character after line continuation
pos = pos \                  # do nothing when not crossing a wall
    + 2*rmask*(llimit-pos) \ # reflect when crossing left,aft&lower walls
    - 2*lmask*(rlimit-pos)   # reflect when crossing right,fore&upper walls
print("Success")
'''

'''
#blackslash, comments = unexpected character after line continuation
pos = pos \             # do nothing when not crossing a wall
+ 2*rmask*(llimit-pos)\ # reflect when crossing left,aft&lower walls
- 2*lmask*(rlimit-pos)  # reflect when crossing right,fore&upper walls
print("Success")
'''
Conclusion
Python does not like what I am doing in an inconsistent way
  • Error: Unexpected indents. When implicitly wrapping lines, python doesn't mind comments but doesn't like indents
  • Error: Unexpected character after line continuation character. When explicitly wrapping lines using backslashes, python doesn't mind indents but doesn't like comments
So here goes a suggestion to the python devs: Is it possible to have python ignore comments after a line continuation character ("\")? This way, the second error would not pop up and python would act as follows:
  • Error: Unexpected indents. When implicitly wrapping lines, python doesn't like indents.
  • Success! When explicitly wrapping lines using backslashes, python doesn't mind indents.
  • Either way, comments are fine.
I think you want parentheses
    pos = (pos 
            + 2*rmask*(llimit-pos) 
            - 2*lmask*(rlimit-pos))
Yep, parenthesis would work well here. Also, you've misinterpreted your Solution 1. Those are being read as separate lines, so pos is not being calculated properly.