Question: Adding a dictionary to a list using the __iadd__ notation seems to add the keys of the dictionary as elements in the list. Why? For example a = [] b = {'hello': 'world'} a += b print(a) # -> ['hello']  The documentation for plus-equals on collections doesn't imply to me that this should happen:  For instance, to execute the statement x += y, where x is an instance of a class that has an __iadd__() method, x.__iadd__(y) is called. If x is an instance of a class that does not define a __iadd__() method, x.__add__(y) and y.__radd__(x) are considered, as with the evaluation of x + y  But, logically, both a + b and b + a raise a TypeError. Furthermore, b += a raises a TypeError too. I don't see any special implementation in the source that would explain things, but I'm not 100% sure where to look. The closest question on SO I found is this one, asking about += on dictionaries, but that's just asking about a data structure with itself. This one had a promising title about list self-addition, but it claims "__add__" is being applied under the hood, which shouldn't be defined between lists and dictionaries. My best guess is that the __iadd__ is invoking extend, which is defined here, and then it tries to iterate over the dictionary, which in turn yields its keys. But this seems... weird? And I don't see any intuition of that coming from the docs.

Answer:  My best guess is that the __iadd__ is invoking extend, which is defined here, and then it tries to iterate over the dictionary, which in turn yields its keys. But this seems... weird? And I don't see any intuition of that coming from the docs.  This is the correct answer for why this happens. I've found the relevant docs that say this- In the docs you can see that in fact __iadd__ is equivalent to .extend(), and here it says:  list.extend(iterable): Extend the list by appending all the items from the iterable.  In the part about dicts it says:  Performing list(d) on a dictionary returns a list of all the keys used in the dictionary  So to summarize, a_list += a_dict is equivalet to a_list.extend(iter(a_dict)), which is equivalent to a_list.extend(a_dict.keys()), which will extend the list with the list of keys in the dictionary. We can maybe discuss on why this is the way things are, but I don't think we will find a clear-cut answer. I think += is a very useful shorthand for .extend, and also that a dictionary should be iterable (personally I'd prefer it returning .items(), but oh well)  Edit: You seem to be interested in the actual implementation of CPython, so here are some code pointers: dict iterator returning keys: static PyObject * dict_iter(PyDictObject *dict) { return dictiter_new(dict, &PyDictIterKey_Type); }  list.extend(iterable) calling iter() on its argument: static PyObject * list_extend(PyListObject *self, PyObject *iterable) { ... it = PyObject_GetIter(iterable); ... }  += being equivalent to list.extend(): static PyObject * list_inplace_concat(PyListObject *self, PyObject *other) { ... result = list_extend(self, other); ... }  and then this method seems to be referenced above inside a PySequenceMethods struct, which seems to be an abstraction of sequences that defines common actions such as concatenating in-place, and concatenating normally (which is defined as list_concat in the same file and you can see is not the same).