0

So I have this function (example):

def monty(x):
  if abs(int(x)) == 1:
    print("Cool!")
    print("Took %s attempts.") % (z)
  elif abs(int(x)) == 0:
    print("Nope.")
  else:
    z = z + 1
    y = x - 1
    monty(y)

Now, of course, 'z' has not yet been defined, so when this function is run so that the 'else' statement is called, the program returns a NameError exception.

Well, ok. Let's try making the statement this:

else:
  try: z
  except NameError: z = 0
  else: z = z + 1
  y = x - 1
  monty(y)

Also assume we added the same NameError catch to the 'if' statement.

The statement always returns 'z' as 0, as the variable is utterly forgotten when 'monty' is ran again. Ok, what if we try defining z outside of 'monty' first, and drop the NameError catch?

Well, it returns a NameError again, and if we instead keep the NameError catch, it still only ever outputs 0.

So, how do I make the function increase z every time it's called validly? In other words, how can I have the program silently count how many times a function was run, to be recalled later? Let's try to avoid adding another argument to the function, for the sake of user-friendliness.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
JessLovely
  • 142
  • 1
  • 12
  • `print("Took %s attempts.") % (z)` won't do what you think it does. `%` is an operator on a string. It needs to go inside the parenthesis: `print("Took %s attempts." % z)` – Patrick Haugh Nov 18 '16 at 17:58
  • @PatrickHaugh: on Python 2 that still happens to work because `print` is a statement and those parentheses around the string are a no-op. But in Python 3 you'd be right. – Martijn Pieters Nov 18 '16 at 18:00
  • @MartijnPieters good point. I saw the parenthesized `print` and assumed. – Patrick Haugh Nov 18 '16 at 18:01
  • Upon further inspection, using (keeping with our example) monty.counter from the linked question does, indeed, work for this. Feel free to close the thread. – JessLovely Nov 18 '16 at 18:17
  • Oh, and, regarding my `print` method, it's how I was taught. Unless you're obsessively counting bytes (cough cough [codegolf.se](http://codegolf.stackexchange.com) cough), it doesn't really matter, and can seem cleaner in some cases. – JessLovely Nov 18 '16 at 18:20
  • Alright! My Collatz Conjecture tester is fully functional. Thanks for the help. – JessLovely Nov 18 '16 at 18:53

1 Answers1

3

Just add z as a keyword argument:

def monty(x, _z=0):
    # ...
    else:
        _z = _z + 1
        y = x - 1
        monty(y, _z)

I renamed z to _z to indicate that it is an implementation detail the end-user doesn't need to worry about. Because keyword arguments have a default, the caller of monty() doesn't have to worry about it.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343