Mixing Tabs & Spaces



Mixing Tabs & Spaces

0 0


tabs-and-spaces

Lightning talk about how to mix tabs and spaces in Python

On Github treyhunner / tabs-and-spaces

Mixing Tabs & Spaces

Trey Hunner / @treyhunner

My name is Trey. I do corporate training and I teach online. My primary programming specialty is Python.

I'm going to teach you how to mix and tabs when indenting your Python code.

Indentation

  • Programmers use indentation to make code readable
  • Python uses indentation to define code blocks
  • Python allows either tabs or spaces for indentation
  • Why not both? 😈

As programmers, we use indentation to make our code readable.

Unlike most other programming languages, Python actually cares about our indentation.

It uses indentation to figure out what our code blocks look like.

In Python, we can use either spaces or tabs for indentation.

But what if we didn't want to choose between tabs and spaces? What if we couldn't decide?

What if we used a mix of both tabs and spaces?

Some programmers just want to mix tabs and spaces

You're probably wondering what kind of indecisive fool would mix tabs and spaces.

That's not what I'm going to talk about though.

I'm not going to tell you why you should mix tabs and spaces, I'm only going to show you HOW.

Indentation doesn't always matter

def flatten(matrix):
  return [
            n for row
 in matrix for n
       in row
     ]
def len_or_none(obj):
   try:
         return len(obj)
   except TypeError:
     return None

First we need to talk about indentation.

Indentation doesn't always matter as much as you might think.

If you're continuing a line by leaving open a parenthesis, bracket, or brace, the indentation doesn't matter at all

If you're making a new indentation level to start a new block of indented code, that first line of code only needs to have greater indentation.

It doesn't matter whether it aligns with some previously indented-block. It just needs to be greater.

Same block? Indentation matters.

def guess_number():
  while True:
     guess = input('Guess: ')
    if guess == '4':
        break
def len_or_none(obj):
  try:
      return len(obj)
    except TyperError:
      return None

However, indentation often does matter.

If you're in the same code block, your indentation level must remain the same. You can't remove a space, you can't add a space.

That if statement on the left is not lined up with the guess variable but it's also not at the same level as the while so it's not inside the while block but it's also not outside it. That is broken code.

That except line on the right isn't in the same block as the try, but it's supposed to be. That's also broken code.

Indentation rules for each line of code

Same block: last line's indentation level Outer block: a previous less-indented level New block: more indented than current indentation

If a line of code is in the same block as the previous line it must be indented the same amount.

If a line of code is supposed to end the current block by being outside of it, it must line up with a previous indentation level.

If a line of code is forming a new code block (for example the first line of an if or a while) it must be more indented than the last line of code.

What about tabs and spaces?

  • Typewriters: tab key moves the cursor to the next tab stop
  • In Python, there's a tab stop at every 8 characters
  • 1 tab character = number of spaces until the next tab stop

Those indentation rules are great, but what about mixing tabs and spaces?

When using tabs it's important to keep in mind that tab characters represent the number of characters until the next 8 character tab stop.

Sometimes we can approximate this idea by saying that tabs are equal to 8 spaces. But that's not quite true.

Let's take a look at some code to see why that is.

Tab stops are 8 characters

def guess_number():
    while True:
	guess = input('Guess: ')
	if guess == '4':
	    break
def guess_number():
    while True:
        guess = input('Guess: ')
	if guess == '4':
	    break

The indentation in these code blocks is highlighted. Every space character is blue and every tab character is red.

These two code samples are equivalent. In the code block on the right you can see that those 8 spaces are seen as equivalent to that 1 tab character.

We can use them interchangeably.

Tabs: not always 8 spaces

def guess_number():
    while True:
	guess = input('Guess: ')
	if guess == '4':
	    break
def guess_number():
    while True:
	guess = input('Guess: ')
    	if guess == '4':
	    break

These two code blocks are also equivalent.

Note that on the right, the if statement line is indented with 4 spaces and 1 tab, but Python sees this as equivalent to 8 spaces.

There is a tab stop every 8 characters in Python.

Tab characters only fill the space needed to reach the next tab stop.

def progressively_more_spaces():
 	print("let's add one more space to the beginning...")
  	print("of each line.")
   	print("The effective indentation is the same")
    	print("even though we're adding more spaces.")
     	print("Each tab represents only the spaces needed")
      	print("to get to the next 8 character tab stop.")
       	if "your editor doesn't use 8 character tabs":
        	print("you may have trouble reading this code.")
         	print("Python uses 8 character tab stops")
          	print("so we also use 8 character tab stops.")
           	print("This way we can mix spaces and tabs")
            	print("without any worries about broken code.")
             	print("Mixing tabs and spaces can be fun")
              	print("but beware!")
               	while "you could write code like this":
                	print("It's probably best not to.")

A line of code with 1 tab is equivalent to a line of code with 1 space and 1 tab.

This is also equivalent to 2 spaces and 1 tab or 7 spaces and 1 tab.

8 spaces and one tab is the same as 2 tabs or 16 spaces.

Configure your editor

# http://editorconfig.org
[*.py]
indent_size = 4
tab_width = 8
indent_style = tab

This is very important: if you are mixing tabs and spaces, you must configure your text editor to use tab stops that are 8 characters wide.

Don't use Python 3

$ python3 examples/demo.py
  File "examples/demo.py", line 3
    print("of each line.")
                         ^
TabError: inconsistent use of tabs and spaces in indentation

Also you can't use python 3.

Python 3 completely disallows indentation styles that use a mix of tabs and spaces.

PEP 373

End Of Life for Python 2.7: 2020

But that shouldn't be a problem because you never really have to upgrade to Python 3.

You can use Python 2 forever.

Don't mix tabs and spaces

Trey Hunner / @treyhunner

Python trainer, on-site & remote http://truthful.technology

Thank you.

Mixing Tabs & Spaces Trey Hunner / @treyhunner My name is Trey. I do corporate training and I teach online. My primary programming specialty is Python. I'm going to teach you how to mix and tabs when indenting your Python code.