I was asked to provide some example code for a job interview and didn't have anything to offer, so I wrote the following function.
A barcode generator may seem a bit basic, but there's some logic behind the choice:
- It's something I recently needed, so it's not entirely contrived.
- It's simple enough to do in one function, so it can be reviewed easily.
- It's complex enough that a new programmer would make a mess of it.
- It's cute. You can render the generated barcode in a browser.
- It's useful, so I could make a little gist out of it.
The barcode is in the Interleaved 2 of 5 Format. It's a simple format, and there's a Wikipedia article that explains it well.
Update: A new version of this code has been posted here. The new code includes many of the suggestions made below.
def render(digits):
'''This function converts its input, a string of decimal digits, into a
barcode, using the interleaved 2 of 5 format. The input string must not
contain an odd number of digits. The output is an SVG string.
import barcode
svg = barcode.render('0123456789')
Strings are used to avoid problems with insignificant zeros, and allow
for iterating over the bits in a byte [for zipping].
# Wikipedia, ITF Format: http://en.wikipedia.org/wiki/Interleaved_2_of_5
'''
# Encode: Convert the digits into an interleaved string of bits, with a
# start code of four narrow bars [four zeros].
bits = '0000'
bytes = {
'0': '00110', '5': '10100',
'1': '10001', '6': '01100',
'2': '01001', '7': '00011',
'3': '11000', '8': '10010',
'4': '00101', '9': '01010'
}
for i in range(0, len(digits), 2):
# get the next two digits and convert them to bytes
black, white = bytes[digits[i]], bytes[digits[i+1]]
# zip and concat to `bits` 5 pairs of bits from the 2 bytes
for black, white in zip(black, white): bits += black + white
# Render: Convert the string of bits into an SVG string and return it.
svg = '<svg height="50">'
bar = '<rect x="{0}" y="0" width="{1}" height="50" {2}></rect>'
pos = 5 # the `x` attribute of the next bar [position from the left]
for i, bit in enumerate(bits):
width = int(bit) * 2 + 2
color = '0,0,0' if (i % 2 == 0) else '255,255,255'
style = 'style="fill:rgb({0})"'.format(color)
svg += bar.format(pos, width, style)
pos += width
return svg + '</svg>'