artsin
artsin

Reputation: 1494

Function as argument in python

I need to pass some function as argument in another function. So, I want to add current time to class attribute every second, for example

import time
class Measurement():
    values = []
    def add_value(self, value):
        print "added value"
        self.values.append(value)


def smart_delay(input_function,args):
    start_time = time.time()
    while 5 > (time.time() -  start_time):
        print "Calling function"
        input_function(args)
        time.sleep(1)

measurement = Measurement()

smart_delay(measurement.add_value,time.time())

Ok, but after checking contents of measurement.values, I get [1425980407.173, 1425980407.173, 1425980407.173, 1425980407.173] - so values are the same!!! What happened? And how to get proper values?

Updated:

Actually, this question is about the way to allow to call some function, passed as the argument to another function. What do you think about this:

import time

class Measurement():
    values = []
    def add_value(self, value):
        print "added value"
        self.values.append(value)


def smart_delay(input_function):
    start_time = time.time()
    while 5 > (time.time() -  start_time):
        print "Calling function"
        input_function()
        time.sleep(1)

measurement = Measurement()

smart_delay(lambda: measurement.add_value(time.time()))

Upvotes: 0

Views: 140

Answers (1)

Mahi
Mahi

Reputation: 21883

Your call to time.time() is executed before the call to smart_delay(...), so smart_delay(measurement.addvalue, time.time()) will first get the return value from time.time() and pass that forward to smart_delay.

You need to pass the time.time function itself, and call it inside of the smart_delay method, instead of passing its return value:

import time
class Measurement():
    values = []
    def add_value(self, value):
        print "added value"
        self.values.append(value)


def smart_delay(output_f, input_f):
    start_time = time.time()
    while 5 > (time.time() -  start_time):
        print "Calling function"
        output_f(input_f())
        time.sleep(1)

measurement = Measurement()

smart_delay(measurement.add_value, time.time)

Notice, that this is not the best way to do what you're doing, but it works.


Here's how I'd do it:

import time

# Why do you need a measurement class which only acts as a list anyways?
my_measurements = []

def repeat(duration, function, args=(), kwargs={}, interval=1):
    """Repeat a function call for the given duration."""
    start_time = time.time()
    while duration > time.time() - start_time:
        function(*args, **kwargs)
        time.sleep(interval)

def add_time_measurement(measurements):
    measurements.append(time.time())

repeat(5, add_time_measurement, (my_measurements,))

And if you want some prints, you can just add them in the add_time_measurement function.

Upvotes: 3

Related Questions