My background is in C, and I'm finally learning this new-fangled "Python" that all the cool kids are talking about.
I want to create a list of formatted hexadecimal values like so:
['0x00','0x01','0x02','0x03' (...) '0xfe','0xff']
Please note that the leading zero's shouldn't be stripped. For example, I want 0x03
, not 0x3
.
My first successful attempt was this:
hexlist=list()
tempbytes = bytes(range(256))
for value in tempbytes:
hexlist.append("0x" + tempbytes[value:value+1].hex())
del tempbytes
But, wow this is ugly. Then I tried to make it more Pythonic ("Pythony"?) like so:
hexlist = ["0x"+bytes(range(256))[x:x+1].hex() for x in bytes(range(256))]
My thoughts:
- OMG! That's harder to read, not easier!
- Not only that, but I had to invoke
range
twice, which I assume is inefficient. - I bet there's a much better way that I haven't been exposed to yet...
My questions:
- Is the second much less efficient?
- Is there a better way to do this?
- What's the best thing to do here in keeping with python style?
1 Answer 1
The shortest and most readable way to do it would probably be
hexlist = [hex(x) for x in range(256)]
Time
Your first : 0.1 ms per loop for \10ドル^5\$ loops
Your second: 1 ms per loop for \10ドル^5\$ loops
The above : 0.02 ms per loop for \10ドル^5\$ loops
I'm unable to com up with a worse example, but there is always a worse way to do it, exactly as there is always preferable way to do it.
Edit To do this with filled zeros I would suggest to treat the first 10 numbers as a special case.
hexlist = [hex(x) if x > 15 else "{:#04x}".format(x) for x in range(256)]
new time: 0.04 ms. Even if it isn't as pretty.
Edit:
And when considering that format can format binary numbers, why not hex?
hexlist = ["{:#04x}".format(x) for x in range(256)]
I guess that this is hard coded for this range, but anyway.
Time: 0.1ms for per loop for \10ドル^5\$ loops.
And more edits
Using old style:.
hexlist = ["0x%02x" % n for n in range(256)]
Time: 0.08ms per loop for \10ドル^5\$ loops.
And specifically generating what we want.
hexlist = ["{:#04x}".format(x) for x in range(16)] + \
[hex(x) for x in range(16, 256)]
Time: 0.03ms per loop for \10ドル^5\$ loops.
-
\$\begingroup\$ Excellent, Simon, thank you. Unfortunately, this strips off the leading zeros from the first 10 values. I wasn't clear in my question: I would like
0x03
, for example, instead of0x3
. I've updated the question... \$\endgroup\$bitsmack– bitsmack2016年11月16日 06:28:44 +00:00Commented Nov 16, 2016 at 6:28 -
\$\begingroup\$ Maybe not as pretty as your first method, but a whole lot prettier than either of mine! :-D Thanks! \$\endgroup\$bitsmack– bitsmack2016年11月16日 06:58:34 +00:00Commented Nov 16, 2016 at 6:58
-
\$\begingroup\$ Glad to help, it was an very interesting question! \$\endgroup\$Simon– Simon2016年11月16日 07:50:20 +00:00Commented Nov 16, 2016 at 7:50
-
\$\begingroup\$ For roughly 0.13 ms per loop (over 10^5 loops), using "old-style" formatting strings,
["0x%02x" % n for in in range(256)]
is short, readable and (probably) fast enough for once-off generation. \$\endgroup\$Vatine– Vatine2016年11月16日 10:17:59 +00:00Commented Nov 16, 2016 at 10:17 -
2\$\begingroup\$ Both your edits are using the Format Specification Mini-Language,
format(x, "#04x")
is the same as"{:#04x}".format(x)
. Also either way you could change them to'0x{:0>{}x}'.format(5, 2)
, or"{:#0{}x}".format(5, 4)
if you don't want a static length. \$\endgroup\$2016年11月16日 10:18:40 +00:00Commented Nov 16, 2016 at 10:18
Explore related questions
See similar questions with these tags.