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 6862117
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T02:37:19+00:00 2026-05-27T02:37:19+00:00

This is a follow-up question to an answer I gave a few days back

  • 0

This is a follow-up question to an answer I gave a few days back. Edit: it seems that the OP of that question already used the code I posted to him to ask the same question, but I was unaware of it. Apologies. The answers provided are different though!

Substantially I observed that:

>>> def without_else(param=False):
...     if param:
...         return 1
...     return 0
>>> def with_else(param=False):
...     if param:
...         return 1
...     else:
...         return 0
>>> from timeit import Timer as T
>>> T(lambda : without_else()).repeat()
[0.3011460304260254, 0.2866089344024658, 0.2871549129486084]
>>> T(lambda : with_else()).repeat()
[0.27536892890930176, 0.2693932056427002, 0.27011704444885254]
>>> T(lambda : without_else(True)).repeat()
[0.3383951187133789, 0.32756996154785156, 0.3279120922088623]
>>> T(lambda : with_else(True)).repeat()
[0.3305950164794922, 0.32186388969421387, 0.3209099769592285]

…or in other words: having the else clause is faster regardless of the if condition being triggered or not.

I assume it has to do with different bytecode generated by the two, but is anybody able to confirm/explain in detail?

EDIT: Seems not everybody is able to reproduce my timings, so I thought it might be useful to give some info on my system. I’m running Ubuntu 11.10 64 bit with the default python installed. python generates the following version information:

Python 2.7.2+ (default, Oct  4 2011, 20:06:09) 
[GCC 4.6.1] on linux2

Here are the results of the disassembly in Python 2.7:

>>> dis.dis(without_else)
  2           0 LOAD_FAST                0 (param)
              3 POP_JUMP_IF_FALSE       10

  3           6 LOAD_CONST               1 (1)
              9 RETURN_VALUE        

  4     >>   10 LOAD_CONST               2 (0)
             13 RETURN_VALUE        
>>> dis.dis(with_else)
  2           0 LOAD_FAST                0 (param)
              3 POP_JUMP_IF_FALSE       10

  3           6 LOAD_CONST               1 (1)
              9 RETURN_VALUE        

  5     >>   10 LOAD_CONST               2 (0)
             13 RETURN_VALUE        
             14 LOAD_CONST               0 (None)
             17 RETURN_VALUE        
  • 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-05-27T02:37:20+00:00Added an answer on May 27, 2026 at 2:37 am

    This is a pure guess, and I haven’t figured out an easy way to check whether it is right, but I have a theory for you.

    I tried your code and get the same of results, without_else() is repeatedly slightly slower than with_else():

    >>> T(lambda : without_else()).repeat()
    [0.42015745017874906, 0.3188967452567226, 0.31984281521812363]
    >>> T(lambda : with_else()).repeat()
    [0.36009842032996175, 0.28962249392031936, 0.2927151355828528]
    >>> T(lambda : without_else(True)).repeat()
    [0.31709728471076915, 0.3172671387005721, 0.3285821242644147]
    >>> T(lambda : with_else(True)).repeat()
    [0.30939889008243426, 0.3035132258429485, 0.3046679117038593]
    

    Considering that the bytecode is identical, the only difference is the name of the function. In particular the timing test does a lookup on the global name. Try renaming without_else() and the difference disappears:

    >>> def no_else(param=False):
        if param:
            return 1
        return 0
    
    >>> T(lambda : no_else()).repeat()
    [0.3359846013948413, 0.29025818923918223, 0.2921801513879245]
    >>> T(lambda : no_else(True)).repeat()
    [0.3810395594970828, 0.2969634408842694, 0.2960104566362247]
    

    My guess is that without_else has a hash collision with something else in globals() so the global name lookup is slightly slower.

    Edit: A dictionary with 7 or 8 keys probably has 32 slots, so on that basis without_else has a hash collision with __builtins__:

    >>> [(k, hash(k) % 32) for k in globals().keys() ]
    [('__builtins__', 8), ('with_else', 9), ('__package__', 15), ('without_else', 8), ('T', 21), ('__name__', 25), ('no_else', 28), ('__doc__', 29)]
    

    To clarify how the hashing works:

    __builtins__ hashes to -1196389688 which reduced modulo the table size (32) means it is stored in the #8 slot of the table.

    without_else hashes to 505688136 which reduced modulo 32 is 8 so there’s a collision. To resolve this Python calculates:

    Starting with:

    j = hash % 32
    perturb = hash
    

    Repeat this until we find a free slot:

    j = (5*j) + 1 + perturb;
    perturb >>= 5;
    use j % 2**i as the next table index;
    

    which gives it 17 to use as the next index. Fortunately that’s free so the loop only repeats once. The hash table size is a power of 2, so 2**i is the size of the hash table, i is the number of bits used from the hash value j.

    Each probe into the table can find one of these:

    • The slot is empty, in that case the probing stops and we know the
      value is not in the table.

    • The slot is unused but was used in the past in which case we go try
      the next value calculated as above.

    • The slot is full but the full hash value stored in the table isn’t
      the same as the hash of the key we are looking for (that’s what
      happens in the case of __builtins__ vs without_else).

    • The slot is full and has exactly the hash value we want, then Python
      checks to see if the key and the object we are looking up are the
      same object (which in this case they will be because short strings
      that could be identifiers are interned so identical identifiers use
      the exact same string).

    • Finally when the slot is full, the hash matches exactly, but the keys
      are not the identical object, then and only then will Python try
      comparing them for equality. This is comparatively slow, but in the
      case of name lookups shouldn’t actually happen.

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

Sidebar

Related Questions

I have touched on this question here , where Christopher gave an answer to
This is a follow-up to this question's answer . How can I modify the
This is a follow up question to the selected answer in this post: Output
This question is a follow-up question to my previous one that can be found
This is a follow up question to that at Can I create a HTML
I have a number of xml files that should follow this format: <root> <question>What
This is a follow up question to this answer: How do I parse XML
This is a follow-up question to my previous question. As suggested in this answer
This is a follow up question from here specifically concerning its answer . From
This questions is a follow up on an answer by Paul Alexander to the

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.