0

I'm just starting to learn python and keep getting an error that I just can't figure out. Any help would be massively appreciated. Basically, I keep getting the following error:

Enter an int: 8

Traceback (most recent call last):
  File "C:\Users\Samuel\Documents\Python Stuff\Find Prime Factors of Number.py", line 16, in <module>
    once_cycle()
  File "C:\Users\Samuel\Documents\Python Stuff\Find Prime Factors of Number.py", line 8, in once_cycle
    while x==0:
UnboundLocalError: local variable 'x' referenced before assignment

I see lots of people are having the same problem, but when I look at what people have told them to do I can't figure it out. Anyway, my code is this. I've re-checked all my indentation and can't see a problem with it. The aim of this program is to find the prime factors of an int (although it's only 90% complete). It's written in Python 2.7.3.

import math
testedInt = float(raw_input("Enter an int: "))
workingInt = testedInt
x = 0

def once_cycle():
    for dividor in range(1, int(math.floor(math.sqrt(testedInt))+1)):
        while x==0:
            print "Called"
            if (workingInt%dividor == 0):
                workingInt = workingInt/dividor
                x = 1
    if (workingInt > 1):
        once_cycle()
    return

once_cycle()

print workingInt

Thanks in advance for any help,

Sam

Sam Heather
  • 1,493
  • 3
  • 19
  • 42

4 Answers4

6

In your one_cycle() function you are at some point assigning to x:

        if (workingInt%dividor == 0):
            workingInt = workingInt/dividor
            x = 1

This makes x a local variable. You are also referring to it with a test:

    while x==0:

but before it is assigned to. This is the cause of your exception.

Either add x = 0 at the start of your function, or declare it a global (if that is what you meant it to be). By the looks of it, you don't use x outside of the function, so you probably didn't mean it to be.

The following works; workingInt is also being modified so it needs to be declared global:

def once_cycle():
    global workingInt
    x = 0

    for dividor in range(1, int(math.floor(math.sqrt(testedInt))+1)):
        while x==0:
            print "Called"
            if (workingInt%dividor == 0):
                workingInt = workingInt/dividor
                x = 1
    if (workingInt > 1):
        once_cycle()
    return

or, simplified:

def once_cycle():
    global workingInt

    for dividor in range(1, int(math.sqrt(testedInt)) + 1):
        while True:
            if workingInt % dividor == 0:
                workingInt = workingInt / dividor
                break
    if workingInt > 1:
        once_cycle()

int(floating_point_number) already takes the floor of a floating point argument.

Note that you end up with an infinite loop if workingInt % dividor is not 0. The first time testedInt is an odd number, this is going to hit you, for example, and your loop will never exit.

Take 11, for example; you'll try the divisors 1, 2, and 3. While 1 is a divisor, workingInt will remain 11 and the loop breaks. Next for loop, the divisor is 2, and workingInt % 2 is not ever going to give you 0, so the loop will continue forever.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I want it to be a variable so that the loop keeps on going unless a criteria is met inside the method that stops it. – Sam Heather Oct 28 '12 at 15:59
  • 3
    @SamHeather: The proper way to do that is to use `while True:` to create an endless loop and then when the condition is met, to use `break` to end the loop. – Martijn Pieters Oct 28 '12 at 16:00
2

You need to declare global variables x, testedInt and workingInt inside one_cycle() in order to access them there:

def once_cycle():
    global x
    global testedInt
    global workingInt
NotGaeL
  • 8,344
  • 5
  • 40
  • 70
1

The x from

x = 0

is not the same as the one from

while x==0:

See Using global variables in a function other than the one that created them for how to use a global variable inside a function.

Community
  • 1
  • 1
1

you need to define 3 globals in your code of once_cycle():

As variables in functions are defined statically, not when the functions are invoked. So python thinks that the variables testedInt,workingInt and x are considered locals by the function and it Raises error.

import math
testedInt = float(raw_input("Enter an int: "))
workingInt = testedInt
x = 0

def once_cycle():
    global x
    global workingInt
    global testedInt
    for dividor in range(1, int(math.floor(math.sqrt(testedInt))+1)):
        while x==0:
            print "Called"
            if (workingInt%dividor == 0):
                workingInt = workingInt/dividor
                x = 1
                if (workingInt > 1):
                    once_cycle()
                return
once_cycle()
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504