1

I've tried to write a function which tries if the GCD of the variable 'a' and 26 is 1, and if not then return the variable pgcd as True in order to quit a 'While'. But the function doesn't change the value of pgcd which stays False so it stays into the 'While'. I don't understand why the value isn't change. Could you help me :)

def couplepgcd(pgcd):
    try:
        assert gcd(a,26) == 1 
        pgcd = True
    except Exception:
        print("a et 26 doivent être premiers entre eux !")
    return pgcd

...

pgcd = False
while pgcd == False:
    [...]
    couplepgcd(pgcd)
Tom Swifty
  • 2,864
  • 2
  • 16
  • 25
  • You probably should just use an if, instead of a try/except. assert should raise AssertionError - usually catching all exceptions is a poor idea. – dstromberg Nov 01 '13 at 16:53

4 Answers4

2

I think it's because you don't save the result of the couplepgcd function.

pgcd = False
while pgcd == False:
    [...]
    pgcd = couplepgcd(pgcd)
Rafael
  • 18,349
  • 5
  • 58
  • 67
  • yeah, the behavior you were expecting is called pass-by-reference in many languages. you could emulate it with something akin to Java's "boxing": http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference – Rob Starling Nov 01 '13 at 16:48
  • Of course, If I forget such a thing, what is the world coming to ! Thanks a lot ! – Alexis CAILLON Nov 01 '13 at 16:52
  • You're welcome. But make sure you also check other answers, especially the ones saying that it's kind of wrong to use assert + try..catch to do the check. I also see a use case for standard IF statement. – Rafael Nov 01 '13 at 16:57
1

The pgcd variable inside of your couplepgcd function is local to that function, so when you call it even if pgcd is changed to True and returned from the function, this does not change the value of the pgcd variable that you are using in the loop condition.

You are also unnecessarily passing in the current value of pgcd into the function, this isn't used anywhere so it isn't necessary.

Here are all of the options you can use to fix this:

  • Assign the return value of the function to the variable pgcd:

    pgcd = False
    while pgcd == False:
        [...]
        pgcd = couplepgcd()
    
  • Use the global statement within the function so that assignment to pgcd within your function overwrites the global variable (this only works if you while loop is in the global scope, or on Python 3.x you could use the nonlocal keyword):

    def couplepgcd():
        global pgcd
        try:
            assert gcd(a,26) == 1 
        except Exception:
            print("a et 26 doivent être premiers entre eux !")
    
  • Use a mutable variable that you modify within the function, for example with a one-element list:

    def couplepgcd(pgcd):
        try:
            assert gcd(a,26) == 1 
            pgcd[0] = True
        except Exception:
            print("a et 26 doivent être premiers entre eux !")
    
    pgcd = [False]
    while not pgcd[0]:
        [...]
        couplepgcd(pgcd)
    
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • also you should avoid `global` for style and maintainability. TCL has a nice compromise keyword called `upvar` that looks upward in the call-stack: http://www.tcl.tk/man/tcl8.6/TclCmd/upvar.htm – Rob Starling Nov 01 '13 at 16:50
  • In Python 3, that's called `nonlocal`. – kindall Nov 01 '13 at 16:55
1

Your couplepgcd function tries to return pgcd even if it hasn't assigned it. If there's an exception, pgcd is never set, and returning it is an error.

In any case your pgcd function seems to be an awfully long-winded way to say:

def couplepgcd(a):
   return gcd(a, 26) == 1

Also, remember that assert statements will be stripped out when your program is run in optimized mode (python -O) which will break the original function. You shouldn't use assert the way you're using it.

You should then be passing in a rather than pgcd (there's no reason to pass that in, since you don't use it and can't change it) and assigning the return value of couplepgcd() to pgcd in your loop. Or, since it's so short, don't bother writing the function in the first place.

kindall
  • 178,883
  • 35
  • 278
  • 309
0

This is not an answer to your question (see the other answers for that), but the method you are using (assert and catching the exception) is not typical for logic control. It is much more common to use an if statement:

def couplepgcd(pgcd):
    if gcd(a,26) == 1:
        pgcd = True
    else:
        print("a et 26 doivent être premiers entre eux !")
    return pgcd
SethMMorton
  • 45,752
  • 12
  • 65
  • 86