1

Is there a simpler way to do the following, which I find myself doing all the time?

>>> hex(ord('H'))
'0x48'
>>> hex(ord('e'))
'0x65'
>>> hex(ord('l'))
'0x6c'
>>> hex(ord('p'))
'0x70'

I suppose something like:

>>> ords = lambda s: [hex(ord(c)) for c in s]
>>> ords('Help')
['0x48', '0x65', '0x6c', '0x70']

But is there something built-in that I can use for this? Or do I need to use the struct module for anything more than a one-byte print/conversion?

samuelbrody1249
  • 4,379
  • 1
  • 15
  • 58
  • 2
    You don't really need that `lambda` there. You can just do `ords = [hex(ord(c)) for c in s]`. – larsks Sep 20 '20 at 01:05
  • What's your end goal? You can also just to `ords = b'Help'`. Now `ords[0]` is `72` (aka `0x48`). – larsks Sep 20 '20 at 01:07
  • @larsks this is to write a helper in `gdb` where I constantly have strings and I need to see how they look (i.e., hex) in a register or memory address. – samuelbrody1249 Sep 20 '20 at 01:07
  • @larsks well it would work if `s` is defined, yes. – samuelbrody1249 Sep 20 '20 at 01:08
  • Or you can `import binascii; print(binascii.hexlify(b'Help'))` – larsks Sep 20 '20 at 01:09
  • 3
    Strings *don't* conceptually "look" any particular way at the byte level. It depends on the text encoding. The internal representation that Python uses is not necessarily useful or interesting to you. It's also not clear what problem you hope to solve by gaining this kind of "view" of a string, as opposed to looking at the individual characters. You should start out by describing the *actual problem you are actually trying to solve, including motivation* - your existing approach to solving the problem is secondary. – Karl Knechtel Sep 20 '20 at 01:09
  • 2
    or ``list(map(hex, (map(ord, s)))`` – Tony Suffolk 66 Sep 20 '20 at 01:10
  • @TonySuffolk66 thanks for that, my first inclination was using `map` but I was having trouble with the syntax of using two functions within it. – samuelbrody1249 Sep 20 '20 at 01:21
  • @Tony The comprehension is simpler and shorter: `[hex(ord(c) for c in s]` – wjandrea Sep 20 '20 at 01:44
  • @wjandrea - possible (although simpler is subjective) but some people prefer using functional paradigm where they can. Just giving an option. Shorter is irrelevant though - Python doesn't care about the length of the expression. The map version does seem to be a bit quicker (around 13% execution time reduction) - horses for courses. – Tony Suffolk 66 Sep 20 '20 at 02:12

1 Answers1

2

Use the function you wrote, but make it a proper def since named lambdas are bad practice. You can then put it somewhere convenient, like a PYTHONSTARTUP file.

def ords(s):
    """
    Return the hex codepoint for each character in string "s", in a list.

    >>> ords('Help')
    ['0x48', '0x65', '0x6c', '0x70']
    """
    return [hex(ord(c)) for c in s]

By the way, since it's always going to be hex, you might want to get rid of the 0x prefixes by using format(ord(c), 'x').

wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • 1
    @samuelbrody1249 I just noticed in the comments you mentioned you're going to use this to analyze data in memory. The problem is, that depends on how they're encoded in memory. This solution will probably work for ASCII and maybe for UTF-32, but not UTF-8, CP1254, etc. – wjandrea Sep 20 '20 at 01:51