No more Indentation problems

I see some similar topics about identation problems, and I cannot find a reason for the Python code to have identation, why not make the whole code rectified to the left margin, if it is possible would be a great help to everybody.

Python uses indentation to indicate structure.

Most other languages use some other method, such as braces, but even in those languages, indentation is recommended for clarity.

So, if you’re going to indent anyway, why not make use of it?

3 Likes

I am an old DOS or CMD language technician, so you can undestand the difference in code formating, the structure that you mentioned, what is the reason of having 2,3 or 4 places indentation in the code, unless there is a definitive rule, like if it is a “def” put 2 indentation.

There’s no way to get rid of indentation in Python, since it is semantically significant. I assume the original reason was aesthetics. If good coding style renders block start/end markers redundant, why not remove them and leave the focus on the code?

If you’re having trouble with consistent indentation, auto-formatters like black, ruff format, or countless others will do the job for you, and many editors can be configured using a generic .editorconfig file to enforce a format per-project.

2 Likes

That is up to the author of the code to decide. But its usual to use a 4 space indent for each level. Using 2, 3 or 8 is no the norm.

It’s the increase of indentation that starts a nested block; how much doesn’t matter. You signal the end of a block by decreasing indentation back to the amount used for the containing block. The following is perfectly valid, if unorthodox:

if foo:
          if bar:
            pass
          elif baz:
                  pass
          pass
else:
   pass

and equivalent to a more standard

if foo:
    if bar:
        pass
    elif baz:
        pass
    pass
else:
    pass

Uniformity of indentation only matters within a block. At the lexical level, each block is bracketed by pair of INDENT/DEDENT tokens, with the INDENT token tagged with the amount of indentation each line within the block requires. For example, you can see how

if foo:
    a = 1
    b = 2
    c = 3
else:
 d = 4
 e = 5
 f = 6

is tokenized:

% python3 -mtokenize tmp.py
0,0-0,0:            ENCODING       'utf-8'
1,0-1,2:            NAME           'if'
1,3-1,6:            NAME           'foo'
1,6-1,7:            OP             ':'
1,7-1,8:            NEWLINE        '\n'
2,0-2,4:            INDENT         '    '
2,4-2,5:            NAME           'a'
2,6-2,7:            OP             '='
2,8-2,9:            NUMBER         '1'
2,9-2,10:           NEWLINE        '\n'
3,4-3,5:            NAME           'b'
3,6-3,7:            OP             '='
3,8-3,9:            NUMBER         '2'
3,9-3,10:           NEWLINE        '\n'
4,4-4,5:            NAME           'c'
4,6-4,7:            OP             '='
4,8-4,9:            NUMBER         '3'
4,9-4,10:           NEWLINE        '\n'
5,0-5,0:            DEDENT         ''
5,0-5,4:            NAME           'else'
5,4-5,5:            OP             ':'
5,5-5,6:            NEWLINE        '\n'
6,0-6,1:            INDENT         ' '
6,1-6,2:            NAME           'd'
6,3-6,4:            OP             '='
6,5-6,6:            NUMBER         '4'
6,6-6,7:            NEWLINE        '\n'
7,1-7,2:            NAME           'e'
7,3-7,4:            OP             '='
7,5-7,6:            NUMBER         '5'
7,6-7,7:            NEWLINE        '\n'
8,1-8,2:            NAME           'f'
8,3-8,4:            OP             '='
8,5-8,6:            NUMBER         '6'
8,6-8,7:            NEWLINE        '\n'
9,0-9,0:            DEDENT         ''
9,0-9,0:            ENDMARKER      ''
2 Likes

Look at “pass” word only, why has to be in that position, wouldn’t be nice if the code is like:
if foo:
if bar:
pass
elif baz:
pass
pass
else:
pass

This looks terrible, it’s unreadable and also unworkable.

You’re not going to change a fundamental piece of syntax in a >30-year-old language, sorry.

Edit: Oh, perhaps you meant to have some indentation in that post? If so, you need to wrap it in triple backticks (```)

Let’s ignore the word pass, since it just one statement of many
available. Suppose your code looked like this:

 if foo:
 if bar:
 x = 1
 elif baz:
 x = 2
 y = 1
 else:
 z = 3

Since any if/elif/else clause can have multiple statements, how do we
know which which branch the line y = 1 belongs? To the elif baz: ?
Or the if foo:, as an additional statement after the if bar: ?

Both are possible without any markers, and both are legitimate depending
on the needs of the programme.

This is why all languages which accept multiple statements in
if/else/while/for style blocks have an indication in the syntax for what
statement belongs to what block. In many languages that involves some
sort of bracketing such as {…} or a begin…end pair of some
kind. In Python the indentation provides that indication.

Regardless of what is used, something is required.

1 Like

Macoga,

I see the exchange and have to ask if you would consider pausing and listening as people try to both answer and perhaps educate you.

You say your experience goes back to the eighties. Some of us go back further and yet adjust to changes as languages evolve.

Many languages, including python, are carefully thought out and there is an overall plan that does not care if you would do it some other way. Nor is this feature likely to change without breaking, well, everything.

Only languages that heavily use things like goto or gosub or have no long and complicated expressions, can get away without grouping constructs.

Take a simple if statement like you use. Technically, it takes a single argument as in:

if (condition) statement

All languages that allow more complex statements with multiple parts and perhaps nested other items like another if within it, must group them so they look like a single entity. Curly braces or parentheses can be used in many languages but python chose indentation. Use it or find a language you prefer but trying to get it changed is not likely to work as has been explained.

It is not a bug but a deliberate choice!

I agree with you all, and thank you for even getting involved on this topic, but through the years I have learn that not all is written on stone, to adjust to changes doesn´t mean to accept everything as it is, that is call innovation, and hope that something good comes out of it.

And now for something completely different - glimpse of history from Guido van Rossum e-mail Re: Tabs, spaces, and indentation:

/…/ My recommendation is to always use tabs on the Mac – then it will
look good on the Mac and at least parse correctly everywhere.

For the same reason I recommend always using tabs on Unix as well
(thus indenting by 8 positions there), but the majority of Python
users seem to be against me.

2 Likes

I have no idea what the context of this recommendation was. I don’t recall anything Mac-specific about 4-column tabs. I can only guess this had something to do with TextEdit (the text editor that shipped with Mac OS at the time; popular 3rd-party editors like BBEdit would certainly have allowed for customizable tab stops).

Tabs are only a good idea if you assume that every bit of indentation should be a multiple of N spaces (for whatever value of N you want). That’s often not the case when you start breaking logical lines into multiple physical lines, especially with implicit linebreaking inside parentheses, such as this example from PEP 8:

# Correct:
# easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

which uses 10 spaces, as the length of the target name influences the “appropriate” amount of indentation independent of whatever tab stops you might choose to use.

(It’s worth noting, too, that the tab recommendation predates PEP 8 by 7 years.)

1 Like

N = 1. Tabs are a good idea.

1 Like

The topic now seems to be about indentation in terms of use of tabs versus spaces.

Much has changed over the years. I lean toward using spaces and not indenting too deeply. As noted in some places tabs can be customized. And indenting eight spaces will rapidly make code wander off the edge of your screen or wrap. The interpreter does not care, but the programmer may not see blocks lined up visually.

Arguably, in the usual non-constant-width fonts, lining things up is not often doable and even tabs can be confusing, such as when they follow invisible spaces.

Another side issue for the OP is that python indentation rules are actually regularly violated with impunity all the time. One of many reasons is that lines can get overly long. As it happens, using techniques within a structure, like a list, lets you break any visual symmetry as in:

if condition:
  pass
  variable = [
    val1,
    val2,
    val3
  ]
  pass
else:
  variable = [
    val1, content1,
    val2, content2,
    val3, content3
  ]

You can re-arrange it in many other ways or have it all on one line. Using a backslash at the end of a line like this allows an emulation of functional programming:

if condition:
   variable = "  HELLO     World!!   ".\
   rstrip()\
   .lstrip()\
   .removesuffix("!")\
   \
   .\
   swapcase()

This will run fine as the lines are reassembled into something normal when you are not looking.

I again thanks the ones that replied to this topic and make me understand a little bit more about the subject. That brought me to create a script to check and correct the indentation of a script, using autopep8.fix

1 Like