patternpythonMinorCanonical
Python Barcode Generator v2
Viewed 0 times
barcodepythongenerator
Problem
This is a complete rewrite of the code posted for review in this question. The question is identical.
The use of recursive functions to implement what appear to be simp
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.
Wikipedia [ITF Format]: http://en.wikipedia.org/wiki/Interleaved_2_of_5
'''
top = ''
bar = ''
barcode = [top.format(len(digits) * 14 + 24)]
byte_map = {
'0': (2, 2, 4, 4, 2), '1': (4, 2, 2, 2, 4),
'2': (2, 4, 2, 2, 4), '3': (4, 4, 2, 2, 2),
'4': (2, 2, 4, 2, 4), '5': (4, 2, 4, 2, 2),
'6': (2, 4, 4, 2, 2), '7': (2, 2, 2, 4, 4),
'8': (4, 2, 2, 4, 2), '9': (2, 4, 2, 4, 2)
}
byte = lambda i: byte_map[digits[i]]
def encode(bits, i=0):
'''Encodes a string of decimal digits. The output's a binary string,
but as a list of ints, all 2s and 4s, rather than zeros and ones, as
the bars in the SVG barcode are rendered 2px wide for zeros, 4px for
ones.'''
if i == len(digits): return bits
for b, w in zip(byte(i), byte(i+1)): bits.extend([b, w])
return encode(bits, i+2)
def svg(bits, i=0, x=4):
'''Converts the list of ints returned by `encode` to a list of SVG
elements that can be joined to form an SVG string.'''
if i == len(bits): return barcode + ['']
b, w = bits[i:i+2]
barcode.append(bar.format(x, b))
return svg(bits, i+2, x+b+w)
# The call to `encode` passes in the itf start code, and the itf end
# code's added to the list that `encode` returns. The complete list
# is passed to `svg`, which returns a list of SVG element strings
# that're joined with newlines to create the actual SVG output.
return '\n'.join(svg(encode([2, 2, 2, 2]) + [4, 2, 2, 0]))The use of recursive functions to implement what appear to be simp
Solution
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:
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
Instead, you can just take the tuple itself and pass that to
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.
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 bitsBecause 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.
Code Snippets
# Avoid this style.
if i == len(digits): return bits
# Use this style.
if i == len(digits):
return 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])for tup in zip(byte(i), byte(i+1)):
bits.extend(tup)Context
StackExchange Code Review Q#49680, answer score: 3
Revisions (0)
No revisions yet.