Python Barcode Generator v2
Your code looks pretty good. There are a few improvements that I can see. 

Firstly, when following PEP8 (the official Python style convention guide) we want to avoid using multiple statements per line:

# Avoid this style.
if i == len(digits): return bits

# Use this style.
if i == len(digits):
    return bits


Because of your use of multiple statements per line, your code looks like it has an extraneous amount of blank lines (another no-no as defined by PEP8). Fixing the statements will also help mitigate the feeling that your code has too many blank lines.



Secondly, I typically try to avoid declaring functions inside of functions (unless I'm doing something REALLY funky: think async plus decorators plus magic). As many of the answers say here, functions inside functions are useful for creating closures and decorators, both of which are not really needed here in your implementation.



Thirdly, in your for loop within encode() you unpack the tuple returned from zip then take those unpacked elements and put them into a list to extend bits:

# Unpack into `b` and `w`
for b, w in zip(byte(i), byte(i+1)):
    # 'Re-pack' back into list
    bits.extend([b, w])


Instead, you can just take the tuple itself and pass that to extend():

for tup in zip(byte(i), byte(i+1)):
    bits.extend(tup)




Finally, your variable names are a tad ambiguous. They can be guessed (if you know ITF format) but we don't want to necessarily assume others know ITF format or require them to have guess what each of our variables are for.