How to check if a function is called for the first time or a subsequent call?

65 Views Asked by At

I have a function

def compute_daily_quantities():
  # compute some quantities, one of which is the variable, value

After the first call to compute_daily_quantities, we need to add a constant, c to value.

How can I check if it's the first or a subsequent call to compute_daily_quantities?

I come from a C++ background, and in C++, we can introduce a static variable within the function to check. I know you can do something similar in Python, but are there other ways in which this can be done in Python?

The solution I was envisioning is:

def compute_daily_quantities():
  # compute some quantities, one of which is the variable, value
  if not hasattr(compute_daily_quantities, "is_first_call"):
    compute_daily_quantities.is_first_call = True
  else:
    value += c

  compute_daily_quantities.is_first_call = False
2

There are 2 best solutions below

4
alex_danielssen On

Rather than using a function, you might want to keep the attribute in a separate class, like this:

class Computer:
    def __init__(self):
        self.is_first_call = False

    def compute_daily_quantities():
      # compute some quantities, one of which is the variable, value
      if not self.is_first_call:
        self.is_first_call = True
      else:
        value += c

You would then need to make sure that you only instantiated a single instance of the class, otherwise your newer classes would be instantiated with the 'first value' flag as False

You might be able to use a singleton pattern, or a class attribute (rather than an instance attribute) to do this in a safer way depending on how exactly you planned to use it.

5
Squarish On

A global variable would be the simplest way to achieve this.

g = 0

def func(val):
    global g
    val += g
    if not g:
        g = 20
    return val


print(func(10)) # 10
print(func(10)) # 30

Depending on how much persistence you want, you can even go as far as to store g inside a file.

Edit: I just thought this through a bit more, and the better way to achieve this would be a hasattr call similar to what OP was thinking of:

def func(val):
    if hasattr(func, 'g'):
        val += func.g
    else:
        func.g = 20
    return val


print(func(10)) # 10
print(func(10)) # 30