Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8017385
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 4, 20262026-06-04T20:49:50+00:00 2026-06-04T20:49:50+00:00

It was my understanding that brackets were nothing more than a wrapper for __getitem__

  • 0

It was my understanding that brackets were nothing more than a wrapper for __getitem__. Here is how I benchmarked this:

First, I generated a semi-large dictionary.

items = {}
for i in range(1000000):
    items[i] = 1

Then, I used cProfile to test the following three functions:

def get2(items):
    for k in items.iterkeys():
        items.get(k)

def magic3(items):
    for k in items.iterkeys():
        items.__getitem__(k)

def brackets1(items):
    for k in items.iterkeys():
        items[k]

The results looked like so:

         1000004 function calls in 3.779 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    3.779    3.779 <string>:1(<module>)
        1    2.135    2.135    3.778    3.778 dict_get_items.py:15(get2)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
  1000000    1.644    0.000    1.644    0.000 {method 'get' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 {method 'iterkeys' of 'dict' objects}


         1000004 function calls in 3.679 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    3.679    3.679 <string>:1(<module>)
        1    2.083    2.083    3.679    3.679 dict_get_items.py:19(magic3)
  1000000    1.596    0.000    1.596    0.000 {method '__getitem__' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {method 'iterkeys' of 'dict' objects}


         4 function calls in 0.136 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.136    0.136 <string>:1(<module>)
        1    0.136    0.136    0.136    0.136 dict_get_items.py:11(brackets1)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {method 'iterkeys' of 'dict' objects}

Is the issue in the way I am benchmarking? I tried replacing the bracket access with a simple “pass” to ensure that the data was actually being accessed, and found that “pass” was running much quicker. My interpretation of this was that the data was indeed being accessed. I’ve also tried appending to a new list, which gave similar results.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-04T20:49:51+00:00Added an answer on June 4, 2026 at 8:49 pm

    First, the disassembly posted by Not_a_Golfer:

    >>> d = {1:2}
    >>> dis.dis(lambda: d[1])
      1           0 LOAD_GLOBAL              0 (d)
                  3 LOAD_CONST               1 (1)
                  6 BINARY_SUBSCR       
                  7 RETURN_VALUE   
    
    >>> dis.dis(lambda: d.get(1))
      1           0 LOAD_GLOBAL              0 (d)
                  3 LOAD_ATTR                1 (get)
                  6 LOAD_CONST               1 (1)
                  9 CALL_FUNCTION            1
                 12 RETURN_VALUE  
    
    >>> dis.dis(lambda: d.__getitem__(1))
      1           0 LOAD_GLOBAL              0 (d)
                  3 LOAD_ATTR                1 (__getitem__)
                  6 LOAD_CONST               1 (1)
                  9 CALL_FUNCTION            1
                 12 RETURN_VALUE
    

    Now, getting the benchmarking right is obviously important to read anything into the results, and I don’t know enough to help much there. But assuming there really is a difference (which makes sense to me), here’s my guesses about why there is:

    1. dict.get simply “does more”; it has to check if the key is present, and if not return its second argument (which defaults to None). This means there’s some form of conditional or exception-catching, so I am completely unsurprised that this would have different timing characteristics to the more basic operation of retrieving the value associated with a key.

    2. Python has a specific bytecode for the “subscription” operation (as demonstrated in the disassembly). The builtin types, including dict, are implemented primarily in C and their implementations do not necessarily play by the normal Python rules (only their interfaces are required to, and there are plenty of corner cases even there). So my guess would be that the implementation of the BINARY_SUBSCR opcode goes more-or-less directly to the underlying C implementations of builtin types that support this operation. For these types, I expect that it is actually __getitem__ that exists as a Python-level method to wrap the C implementation, rather than that the bracket syntax invokes the Python-level method.

    It might be interesting to benchmark thing.__getitem__(key) against thing[key] for an instance of a custom class that implements __getitem__; you might actually see the opposite results there as the BINARY_SUBSCR op-code would internally have to fall back to doing equivalent work to looking up the method and invoking it.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

So it's my understanding that on a ReaderWriterLock (or ReaderWriterLockSlim more specifically), both the
I don't have a real reason for doing this, other than to gain understanding,
It's my understanding that the Java compiler produces byte code, not object code. First
I am sure this has more to do with my understanding of the behaviour
It's my understanding that position: absolute is absolute to the first parent who has
I've had the understanding that simplejson is much faster than the native json in
It is my understanding that every type (other than some primitives like int and
This is a question for the .NET philosophers: It is my understanding that Microsoft
It's my understanding that GHC gives each thread a stack. Why is this necessary?
Understanding that I should probably just dig into the source to come up with

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.