How to define a Global variable in python? - python

I am newbee in Python . JUst wandering if it is possible to define a Global variable in Python.
I have this python code to compute total number of times Fib(2) has been accessed. But count is printing 0 when called.
import sys
def fib(n):
"""Takes input a natural number n > 0.
Returns n! """
global count
count = 0
if n == 1 or n == 0:
return 1
else:
if n == 2:
print 'encountered here::: '
count += 1
return fib(n-1) + fib(n-2)
def main():
x = int(raw_input('Enter a natural number > 0 :'))
print 'Fibonacci(%d) = %d' % (x, fib(x))
print 'Count =', count
if 1:
main()

A variable defined in the module outside of any function is considered a global variable. To modify a global variable inside of a function, you must write global variableName inside of the function.
You did this, however, that variable is only defined in your function, it must also be declared outside of the function to be considered a global variable. If not, it will be local to your function, despite the global in front of it.
TL;DR Also declare the variable outside of your function.
EDIT (I was wrong):
By writing global variableName in a function and executing said function, it does make the variable a global variable; if not you would be getting a NameError when you tried to print it.
The reason that you're getting a 0, however, is because everytime you call your function, you initialize count to 0. Nonetheless, the solution about still holds.

Move count = 0 outside your fib(n) function. You only need to declare it as global count once inside the function, while the initialization should be outside. What you're doing is that you are re-initializing it with 0 every time the function is called.
import sys
count = 0
def fib(n):
"""Takes input a natural number n > 0.
Returns n! """
global count
if n == 1 or n == 0:
return 1
else:
if n == 2:
print 'encountered here::: '
count += 1
return fib(n-1) + fib(n-2)
def main():
x = int(raw_input('Enter a natural number > 0 :'))
print 'Fibonacci(%d) = %d' % (x, fib(x))
print 'Count =', count
if 1:
main()
Although, you should avoid global variables.

global foo
foo = [1,2,3]
Now foo can be used anywhere in the program

Put the count = 0 outside the function.

Related

Passing arguments to the function (Python, OOP, functions)

So here we are passing 2 arguments to the function: 1) a just created object from the class (counter) and 2) a number (0).
def increment(c, num):
c.count += 1
num += 1
class Counter:
def __init__(self):
self.count = 0
counter = Counter()
number = 0
for i in range(0, 100):
increment(counter, number)
print(
"counter is "
+ str(counter.count)
+ ", number of times is "
+ str(number)
)
The result of the code is the following:
# counter is 100, number of times is 0
Why the 'number' variable does not increase, if the function clearly says:
num += 1
???
Python passes parameters by object reference, which results basically in having references to mutable types and values for immutable types.
Counter is a mutable class that you have created, whereas number is an integer (immutable).
As described in the other answers and comments, the immutable integer is overriden but since it is a local variable you cannot see these changes outside the function except if you return the value of num from increment.
Alternatively, you could make number a class variable of Counter. Hereby, you could track how many times any instance of Counter has ever increased the count:
class Counter:
number_increases = 0
def __init__(self):
self.count = 0
def increase(self):
self.count += 1
Counter.number_increases += 1
c1 = Counter()
c2 = Counter()
for i in range(10):
c1.increase()
print(f"counters are {c1.count} and {c2.count}; " +
f"number of times is {Counter.number_increases}")
for i in range(20):
c2.increase()
print(f"counters are {c1.count} and {c2.count}; " +
f"number of times is {Counter.number_increases}")
Output:
counters are 10 and 0; number of times is 10
counters are 10 and 20; number of times is 30
Every time the function is called the value is assigned to a new variable called num. I will not modify the variable.
So,
You have to return the value of number from the increment function and assign it to the number variable.
def increment(c, num):
c.count += 1
return num+1
class Counter:
def __init__(self):
self.count = 0
counter = Counter()
number = 0
for i in range(0, 100):
number = increment(counter, number)
print(
"counter is "
+ str(counter.count)
+ ", number of times is "
+ str(number)
)
Output
counter is 100, number of times is 100
The best way is to add increment function in the Counter class. But If you want to do this with function this way works fine.
That is because whenever you pass an argument to a function in python, you are using a copy of that argument, so writing n += 1 will have no effect on the actual variable n outside of the function. You can try writing:
def increment(c, num):
c.count += 1
return num+1
and in the for loop you can do like this:
for i in range(100): # range(0, 100) is the same as range(100)
# because 0 is the default value for start
number = increment(counter, number)
That should work.

Trying to keep count of random number occurrences through if statement

I'm trying to keep a count of the amount of times a random number is generated and stop it after a certain number has been hit. I'm new to python there's probably a simple fix that I can't see.
p = 0
def gameplay():
i = random.randint(1,2)
if i <= 1:
print(1)
p = p + 1
gameplay();
else:
print(2)
p = p + 1
gameplay();
if p <= 10:
gameplay();
I keep getting the error: "local variable 'p' referenced before assignment"
p = 0
def gameplay(p):
i = random.randint(1,2)
if i <= 1:
print(1)
else:
print(2)
p = p + 1
return p
while p <= 10:
p = gameplay(p)
I edited your code, so that p is incremented in the gameplay-function and then returned to the variable 'p' again. Thereby eliminating your error and the need for a global variable p.
I changed the if-statement to a while loop, because I thought that the sample code tried to implement a recursive function that ran until p was larger than 10. If that's not what you want, just change it back to an if-statement, but then make sure p gameplay(p) gets called somewhere else in your code.

Why do I get a NameError: name 'counter' is not defined, while I set the counter variable to global?

Below is my code. I don't know what I am doing wrong, but when I run this, I get NameError: name 'counter' is not defined. I'm learning Python from a textbook and according to the textbook my code is right. I can't find the difference between the textbook code and this code... I've seen other questions on stackoverflow about global variables, but I still can't figure out what I did wrong. Why do I get this error? And how to solve it?
UPDATE:
I know what I did wrong. I should write counter = 0 above the function.
def rpower(a, n):
'returns a to the nth power'
global counter # counts number of multiplications
if n == 0:
return 1
# if n > 0:
tmp = rpower(a, n//2)
if n%2 == 0:
counter += 1
return tmp*tmp # 1 multiplication
else:
counter += 2
return a*tmp*tmp # 2 multiplications
print(rpower(2, 10000))
May be your counter variable is declared outside of you function. Like:
counter=0
def rpower(a, n):
'returns a to the nth power'
global counter # counts number of multiplications
if n == 0:
return 1
# if n > 0:
tmp = rpower(a, n//2)
if n%2 == 0:
counter += 1
return tmp*tmp # 1 multiplication
else:
counter += 2
return a*tmp*tmp # 2 multiplications
print(rpower(2, 10000))
I rewrite your code a little bit in PyCharm. Just changed the name of the function, because your code didn't worked by just ctrl+v:
def rpow(a, n):
global counter
if n == 0:
return 1
tmp = rpow(a, n/2)
if n%2 == 0:
counter += 1
return tmp*tmp
else:
counter += 2
return a*tmp*tmp
print(rpow(2, 10000))
I don't got your error, but i reached RecursionError: maximum recursion depth exceeded in comparison
Try to do the same.

Return outside function error in Python

This is the problem:
Given the following program in Python, suppose that the user enters the number 4 from the keyboard. What will be the value returned?
N = int(input("enter a positive integer:"))
counter = 1
while (N > 0):
counter = counter * N
N = N - 1
return counter
Yet I keep getting a outside function error when I run the system
what am I doing wrong?
Thanks!
You can only return from inside a function and not from a loop.
It seems like your return should be outside the while loop, and your complete code should be inside a function.
def func():
N = int(input("enter a positive integer:"))
counter = 1
while (N > 0):
counter = counter * N
N -= 1
return counter # de-indent this 4 spaces to the left.
print func()
And if those codes are not inside a function, then you don't need a return at all. Just print the value of counter outside the while loop.
You have a return statement that isn't in a function. Functions are started by the def keyword:
def function(argument):
return "something"
print function("foo") #prints "something"
return has no meaning outside of a function, and so python raises an error.
You are not writing your code inside any function, you can return from functions only. Remove return statement and just print the value you want.
As already explained by the other contributers, you could print out the counter and then replace the return with a break statement.
N = int(input("enter a positive integer:"))
counter = 1
while (N > 0):
counter = counter * N
N = N - 1
print(counter)
break
It basically occours when you return from a loop you can only return from function

Access a method's local variables in Python

Was going through a Python Tutorial and have asked a related question here(Code from my previous example and thanks to #emmanuel)
Code:
import math, time
class PrimeFactor:
def __init__(self):
pass
def isprime(self,number):
start=time.clock()
fnum = [1,]
print "Reticulating Splines..."
last = int(math.ceil(math.sqrt(number)))
for p in range(2, last + 1):
if (number % p) == 0:
fnum.append(p)
fnum.append(number / p)
# Remove duplicates, sort list
fnum = list(set(fnum))
fnum.sort()
end=time.clock()
if len(fnum) > 1:
return number, "is not a prime because of these factors", fnum ,"Time taken", end-start
else:
return True, "Time taken", end-start
print "Prime or factor calculator v3 using sqrt(n)"
print #
num =int(raw_input("Enter number: "))
eg=PrimeFactor()
print eg.isprime(num)
From this code, I tried to get the variable fnum which is local to the function(method) isprime, which contains the factor list. Accessing it by calling
print eg.isprime(num).fnum
gave me a error
AttributeError: 'tuple' object has no attribute 'fnum'
I guess I cannot call a local variable that way.
Plus the code is not reusable. So I decided to do a rewrite, to make it more modular.
Rewritten Code:
import math
class PrimeFactor:
def __init__(self):
pass
def isPrime(self,number):
fnum = [1,]
last = int(math.ceil(math.sqrt(number)))
for p in range(2, last + 1):
if (number % p) == 0:
return False
else:
return True
def getFactors(self,number):
fnum = [1,]
last = int(math.ceil(math.sqrt(number)))
for p in range(2, last + 1):
if (number % p) == 0:
fnum.append(p)
fnum.append(number / p)
# Remove duplicates, sort list
fnum = list(set(fnum))
fnum.sort()
if len(fnum) > 1:
return fnum
else:
return None
num =int(raw_input("Enter number: "))
eg=PrimeFactor()
if eg.isPrime(num):
print num, "is a Prime Number"
else:
print num, "is not a prime number"
print "Factors", eg.getFactors(num)
I had to forgo time calculation. I can calculate time while using an instance.
Question:
Can I access the local variable fnum in my previous example? If yes, How?(I guess no). If no, then is the rewritten code good enough or am I doing it wrong?
The problem with your modification is that you're duplicating the calculus. I understand you just want to get the calculated factors, which just involves creating fnum as an attribute:
import math, time
class PrimeFactor:
def __init__(self):
self.fnum = [1,]
self.elapsedTime = 0
def getElapsedTime(self):
return self.elapsedTime
def getFactors(self):
return self.fnum
def isprime(self,number):
start=time.clock()
self.fnum = [1,]
last = int(math.ceil(math.sqrt(number)))
for p in range(2, last + 1):
if (number % p) == 0:
self.fnum.append(p)
self.fnum.append(number / p)
# Remove duplicates, sort list
self.fnum = list(set(self.fnum))
self.fnum.sort()
end=time.clock()
self.elapsedTime = end-start
return (not len(self.fnum) > 1 )
num =int(raw_input("Enter number: "))
eg=PrimeFactor()
if eg.isprime(num):
print num, "is a Prime Number", eg.isprime(num)
else:
print num, "is not a prime number"
print "Factors", eg.getFactors()
print eg.getElapsedTime()
You could even develop the code a little bit more and take advantage of the previous calculated factors, thus using dynamic programming.
Hope this helps.
You need:
print eg.isprime(num)[2]
(your method is returning a tuple, and you need the third member, that's all)
There is no way to access the local variables of a function from outside that function. You need to explicitly make them available to callers, either by returning them, or by writing their values into a container available to the caller.

Categories

Resources