Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create a function which will return a dictionary with two functions in that will increment/decrement a count in Python?

I've been tasked with creating a function "make_counter" which takes a number as its only argument. It should return a dictionary containing two functions that can be invoked to increment and decrement the number and then return it.

The behaviour should be as follows:

counter = make_counter(10)
up = counter['up']
down = counter['down']
print(up()) # 11
print(down()) # 10
print(down()) # 9
print(up()) # 10

with these being the answers it gives out.

However I've tried the following:

def make_counter(num):

    def up(num = num):
        num += 1
        return num
        
    def down(num = num):
        num -= 1
        return num
        
    return {"up": up, "down": down}
counter = make_counter(10)
up = counter["up"]
down = counter["down"]

print(up()) # 11
print(down()) # 9
print(down()) # 9
print(up()) #11

And these are the answers I get instead, ie. it doesn't remember the count.

I don't understand why this exact solution works in JavaScript but the equivalent doesn't work here in Python. And furthermore, why the inner functions in Python require default arguments or they can't "see" what num is from the parent function outside. Any help would be appreciated.

like image 390
omega_geezy Avatar asked Apr 17 '26 22:04

omega_geezy


2 Answers

You're incrementing the local variable num. You need to use a closure variable. Use the nonlocal keyword to make num refer to the variable in the enclosing function.

def make_counter(num):

    def up():
        nonlocal num
        num += 1
        return num
        
    def down():
        nonlocal num
        num -= 1
        return num
        
    return {"up": up, "down": down}
like image 103
Barmar Avatar answered Apr 20 '26 14:04

Barmar


I would make a class with a pair of methods

class Counter:
    def __init__(self, num):
        self.num = num

    def inc(self):
        self.num += 1
        return self.num

    def dec(self):
        self.num -= 1
        return self.num

Then your function can create an instance of this class and return bound methods which operate on the instance's state

def make_counter(num):
    c = Counter(num)
    return {'up': c.inc, 'down': c.dec}

Usage

>>> counter = make_counter(10)
>>> up = counter['up']
>>> down = counter['down']
>>> up()
11
>>> down()
10
>>> down()
9
>>> up()
10
like image 45
Cory Kramer Avatar answered Apr 20 '26 12:04

Cory Kramer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!