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.
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}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With