Trying to understand this phenomenon in Python. When I wrap my code into a function, it speeds up by more than 30%!!! So far I failed to google out any reasonable explanation.
For example:
import sys
sys.stdin = open("dd.txt")
import cProfile
import time
t0 = time.time()
def main():
    from collections import defaultdict
    n, T = map(int, raw_input().split())
    tree = defaultdict(lambda: set())
    root = None
    for _ in xrange(n - 1):
        a, b = map(int, raw_input().split())
        tree[a].add(b)
        tree[b].add(a)
        if not root:
            root = a
    count = 0
    stack = [root]
    links = dict()
    links[root] = 0
    mem = dict()
    while stack:
        node = stack.pop()
        path = list()
        path.append(node)
        lnk = links[node]
        while lnk:
            if lnk not in mem:
                if abs(lnk - node) <= T:
                    count += 1
                path.append(lnk)
                lnk = links[lnk]
            else:
                path.extend(mem[lnk])
                for el in mem[lnk]:
                    if abs(el - node) <= T:
                        count += 1
                break
        #print node, path
        plen = len(path)
        mem[node] = path
        for next_node in tree[node]:
            if plen <= 1 or next_node != path[1]:
                links[next_node] = node
                stack.append(next_node)
    print count
main()
print time.time() - t0
This prints running time as 2.5 seconds, but this:
import sys
sys.stdin = open("dd.txt")
import cProfile
import time
t0 = time.time()
#def main():
from collections import defaultdict
n, T = map(int, raw_input().split())
tree = defaultdict(lambda: set())
root = None
for _ in xrange(n - 1):
    a, b = map(int, raw_input().split())
    tree[a].add(b)
    tree[b].add(a)
    if not root:
        root = a
count = 0
stack = [root]
links = dict()
links[root] = 0
mem = dict()
while stack:
    node = stack.pop()
    path = list()
    path.append(node)
    lnk = links[node]
    while lnk:
        if lnk not in mem:
            if abs(lnk - node) <= T:
                count += 1
            path.append(lnk)
            lnk = links[lnk]
        else:
            path.extend(mem[lnk])
            for el in mem[lnk]:
                if abs(el - node) <= T:
                    count += 1
            break
    #print node, path
    plen = len(path)
    mem[node] = path
    for next_node in tree[node]:
        if plen <= 1 or next_node != path[1]:
            links[next_node] = node
            stack.append(next_node)
print count
#main()
print time.time() - t0
Simply moving code out of main() function makes it run 3.5 seconds instead of 2.5.
What can be the reason for this???
 
     
    