How do you override the result of unpacking syntax *obj and **obj?
For example, can you somehow create an object thing which behaves like this:
>>> [*thing]
['a', 'b', 'c']
>>> [x for x in thing]
['d', 'e', 'f']
>>> {**thing}
{'hello world': 'I am a potato!!'}
Note: the iteration via __iter__ ("for x in thing") returns different elements from the *splat unpack.
I had a look inoperator.mul and operator.pow, but those functions only concern usages with two operands, like a*b and a**b, and seem unrelated to splat operations.
*iterates over an object and uses its elements as arguments.**iterates over an object'skeysand uses__getitem__(equivalent to bracket notation) to fetch key-value pairs. To customize*, simply make your object iterable, and to customize**, make your object a mapping:If you want
*and**to do something besides what's described above, you can't. I don't have a documentation reference for that statement (since it's easier to find documentation for "you can do this" than "you can't do this"), but I have a source quote. The bytecode interpreter loop inPyEval_EvalFrameExcallsext_do_callto implement function calls with*or**arguments.ext_do_callcontains the following code:which, if the
**argument is not a dict, creates a dict and performs an ordinaryupdateto initialize it from the keyword arguments (except thatPyDict_Updatewon't accept a list of key-value pairs). Thus, you can't customize**separately from implementing the mapping protocol.Similarly, for
*arguments,ext_do_callperformswhich is equivalent to
tuple(args). Thus, you can't customize*separately from ordinary iteration.It'd be horribly confusing if
f(*thing)andf(*iter(thing))did different things. In any case,*and**are part of the function call syntax, not separate operators, so customizing them (if possible) would be the callable's job, not the argument's. I suppose there could be use cases for allowing the callable to customize them, perhaps to passdictsubclasses likedefaultdictthrough...