oezguensi
oezguensi

Reputation: 950

Function wrapper for multiple code lines in Python

I would like to wrap some code around a function (e.g. print timing information) and reuse this function for multiple code blocks:

start = time.time()
print('Started adding numbers at {}'.format(start))
a = 1
b = 2
c = a + b
end = time.time()
print('Finished adding numbers in {} seconds'.format(end - start)')

Is it possible to wrap multiple lines of code into a wrapper function, without defining functions for each code blocks? One way would be to define a function and use a decorator but I would like to avoid doing this for every code block:

@print_time
def foo():
    a = 1
    b = 2

    return a + b

Upvotes: 1

Views: 1180

Answers (4)

Big Bro
Big Bro

Reputation: 944

One other way is to use context managers.

For example:

from contextlib import contextmanager

@contextmanager
def timer():
    start = time.time()
    print('Started adding numbers at {}'.format(start))
    yield
    end = time.time()
    print('Finished adding numbers in {} seconds'.format(end - start))


# Then call it like that
with timer():
    a = 1
    b = 2
    c = a + b

Upvotes: 1

Matt C
Matt C

Reputation: 177

You could create a context manager class and execute your code in a with block. This would make for a compact and highly reusable timer function. Something like this:

import time

class TimeClass():
    def __init__(self):
        pass
    def __enter__(self):
        self.start = time.time()
    def __exit__(self, type, value, traceback):
        self.end = time.time()
        print('Finished executing in {} seconds'.format(self.end - self.start))

You could use the class like this:

with TimeClass():
    # your code
    pass

Check this link out for more details.

Upvotes: 3

FloLie
FloLie

Reputation: 1840

Alternative what do you think about this:

You define a timer class, that keeps timers in store by name e.g. Description for the code block, and put all the prints and dos you like as optins in the stop_timer function. It is still two lines of code, but I dont think you will get less then that

import time as t

class myTimer:
    def __init__(self):
        self.timers = {}
    def start_timer(self, name):
        print('Started adding numbers at {}'.format(t.time()))
        self.timers[name] = t.time()
    def stop_timer(self,name):
        runtime = t.time() - self.timers[name]
        del(self.timers[name])
        print('Finished adding numbers in {} seconds'.format(runtime))
        return runtime

timer = myTimer()


timer.start_timer('First Timer')
timer.start_timer('Second Timer')
a = 1
t.sleep(1)
b = 2
timer.stop_timer('First Timer')
c = 3
t.sleep(2)
d = 4
timer.stop_timer('Second Timer')

Returns

Started adding numbers at 1606676633.8297324
Started adding numbers at 1606676633.8297324
Finished adding numbers in 1.0228865146636963 seconds
Finished adding numbers in 3.0250420570373535 seconds

Upvotes: 1

FloLie
FloLie

Reputation: 1840

Yu can do this using higher order functions such as:

def inner():
    pass

def outer(inner):
    inner()

and then call

outer(inner)

Upvotes: 0

Related Questions