0

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()))
4
  • 2
    Why wouldn't it be? You passed it the result of calling time.time(), that won't subsequently change. Commented Mar 10, 2015 at 9:50
  • smart_delay(measurement.add_value,time.time()) causes the same value to be passed as the argument to measurement.add_value() each iteration of your loop. Commented Mar 10, 2015 at 9:51
  • In Python all arguments are resolved / evaluated before function execution - in your case first argument would be unbound method instance, and second would be float returned by time.time() Commented Mar 10, 2015 at 9:54
  • So, there is no way to call function with arguments, returned from another function, isn't it? Commented Mar 10, 2015 at 10:02

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

It is a pity, that I cannot to call function like smart_delay(some_expression), when some_expression can be any mixture of methods or function.
@artsin How would you expect it to work? In your case, how do you expect Python to know if you want to call the smart_delay(time.time()) with the return value from time.time() or to call the function time.time over and over again? As you learn more Python, it'll only start to make sense that it works the way it does :) Simply because it doesn't work like you wanted it to, doesn't mean it's a pity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.