DEV Community

Satyam Kumar Sinha
Satyam Kumar Sinha

Posted on • Updated on

Which is faster dict() vs {} and why?

dict() internally calls below opcodes:

Image description

  1. LOAD_NAME : Pushes the value associated with co_names[namei] onto the stack. So, whatever names have been declared are pushed to the interpreter stack through this OPCODE.

  2. PRECALL : Prefixes CALL. Logically this is a no op. It exists to enable effective specialization of calls. argc is the number of arguments as described in CALL.

  3. CALL : Calls a callable object with the number of arguments specified by argc(in PRECALL), including the named arguments specified by the preceding KW_NAMES, if any. On the stack are (in ascending order), either:

    1. NULL
    2. The callable
    3. The positional arguments
    4. The named arguments

    or:

    1. The callable
    2. self
    3. The remaining positional arguments
    4. The named arguments

    argc is the total of the positional and named arguments,
    excluding self when a NULL is not present.

    CALL performs below steps:

    1. pops all arguments(key-value pairs) and the callable object(here, dict) off the stack
    2. calls the callable object(here, dict) with arguments if any.
    3. pushes the return value returned by the above callable object(here, dict)
    4. In brief, initialises the new object passing the keyword arguments to its initialisation method. Here, dict is called.

When we initialise the dict() with some key-value pairs as dict(a="A", b="B", c="C", d="D"):
OPCODES image:

Image description

The process :

  1. LOAD_NAME : loads the name of the object to be called and initialised, here it is dict as seen in the above image.
  2. LOAD_CONST: Pushes co_consts[consti] onto the stack. As we see in the above image, first 'A' is pushed then, 'B' and so on in the order they were defined in the code.
  3. KW_NAMES : Prefixes PRECALL. Stores a reference to co_consts[consti] into an internal variable for use by CALL. co_consts[consti] must be a tuple of strings. In other words, an internal variable(dictionary) is used to store all the key-value pairs defined/declared above and was pushed into the stack. These are thereafter used as arguments to CALL.
  4. PRECALL : argc is 4, the total number of arguments.
  5. CALL : 4 keyword arguments are used to make the call, initialise and create the dictionary object in this case.

Conclusion:
1. pushes the object to be created(dict) onto the stack using LOAD_NAME
2. pushes the key-value pairs if any using LOAD_CONST onto the stack as constant values.
3. pop out the key-value pairs off of the stack and create a dictionary to hold the keyword arguments to the function
4. The constructor for dict is called to make a new object
5. Initialise the new object by passing the keyword arguments to its initialisation method.
6. Resize the new dict and copy the key-value pairs into it from the keyword arguments.

The same should be the case with (1, ) vs tuple(), [] vs list().

References:

  1. https://docs.python.org/3/library/dis.html
  2. https://doughellmann.com/posts/the-performance-impact-of-using-dict-instead-of-in-cpython-2-7-2/

Top comments (0)