I was hacking up a grotty (but neat!) python plugin for gdb last night, and ran into a quirk I didn’t really understand. I had a list of numbers, and was using struct to make a suitable memory buffer for gdb.selected_inferior().write_memory. Except, it wasn’t quite working….
import struct q = [1,2,3,4] x = struct.pack("<4H", q) Traceback (most recent call last): File "<stdin>", line 1, in <module> struct.error: pack requires exactly 4 arguments |
I wasn’t really expecting this, normally things “just work” and python “does the right thing” (Computer! Do as I want, not as I say!) StackOverflow gave me the gem of using the * operator.
import struct q = [1,2,3,4] struct.pack("<4H", *q) '\x01\x00\x02\x00\x03\x00\x04\x00' |
OK, well and good, but WTF?! Where did that come from? Turns out it’s not an operator per se, but part of the call syntax. So * turns a list into a string of positional arguments, and ** turns a dict into a set of keyword arguments, like so.
def gofish(where, when): print(where, when) gofish("lake", "tomorrow") ('lake', 'tomorrow') gofish({"where" : "a river", "when": "next weekend"}) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: gofish() takes exactly 2 arguments (1 given) gofish(**{"where" : "a river", "when": "next weekend"}) ('a river', 'next weekend') |
So there, a rather esoteric corner of python I’d never seen before.
Leave a Comment