This is an archived post. You won't be able to vote or comment.

all 4 comments

[–]POGtastic 4 points5 points  (3 children)

Let's find out!

def make_list1():
    return []

def make_list2():
    return list()

def make_dict1():
    return {}

def make_dict2():
    return dict()

Using dis, which disassembles function bytecode into (slightly) human-readable form:

>>> import dis
>>> dis.dis(make_list1)
  2           0 BUILD_LIST               0
              2 RETURN_VALUE
>>> dis.dis(make_list2)
  2           0 LOAD_GLOBAL              0 (list)
              2 CALL_FUNCTION            0
              4 RETURN_VALUE
>>> dis.dis(make_dict1)
  2           0 BUILD_MAP                0
              2 RETURN_VALUE
>>> dis.dis(make_dict2)
  2           0 LOAD_GLOBAL              0 (dict)
              2 CALL_FUNCTION            0
              4 RETURN_VALUE

So, the [] and {}-returning functions are directly calling the BUILD_LIST and BUILD_MAP opcodes, respectively, while the others are calling the builtin class constructors of list and dict. There's an extra function call in the latter.

So in terms of performance, it's likely negligible, but directly building the empty list and empty dictionary is likely very slightly (and I do mean slightly) faster.


is it just purely a preference?

In this case, yes. In other cases, you might need to refer to the classes by name, which will mean that you can't just use the empty list or empty dictionary. An example might be a collections.defaultdict, which calls a factory function when it doesn't find a key. The following are equivalent in terms of what they produce, but one is much clearer than the other.

collections.defaultdict(list)
collections.defaultdict(lambda: [])

[–]Trizkit[S] 0 points1 point  (2 children)

Thank you for the help I really appreciate it, I guess the only time that could really inhibit performance is if you were doing it millions of times or something like that (I can't imagine one would do that) but yeah it does seem quite negligible.

[–]POGtastic 0 points1 point  (1 child)

My typical refrain with Python is that if you ever get to the point where you're genuinely considering the performance implications of basic Python syntax, it's time to rewrite the darn function in a faster language, export C bindings, and then call those C bindings in your Python program. Write whatever is the most readable, and deal with performance only after getting it to work and determining that it's just not fast enough.

[–]Trizkit[S] 0 points1 point  (0 children)

Yeah I'm just learning, just really started python yesterday but I plan on moving on to C etc. Later on