local variable 'n' referenced before assignment. Closures - python

def fibonacci_closure(n):
def fibonaci():
if n == 0: """in this line error occured idk why because in watches i see n=4"""
return 0
elif n == 1 or n == 2:
return 1
else:
i = 1
j = 1
tmp = 1
while n != 2:
n -=1
tmp = i
i = j + i
j = tmp
return i
return fibonaci
a = fibonacci_closure(4)
a()
Task:
Return a closure that will generate elements of the Fibonacci sequence when called repeatedly.
Example:
g = fibonacci_closure()
g() # 1
g() # 1
g() # 2
g() # 3
UnboundLocalError: local variable 'n' referenced before assignment

Fibonacci numbers are a typical example for generators. It's only irritating why the function should return a function instead of a generator.
def fibonacci_closure():
def fibonacci():
i = j = 1
while True:
yield i
i, j = j, i + j
return fibonacci().__next__

The task you are trying to accomplish could be done by creating a class. (Or you could look into creating a 'generator' object, which is its own separate thing.)
What you need in order to preserve the value of n from one call to the next is some sort of global variable. Global variables in Python are possible, but are bad practice. The same thing can be accomplished from within a class where n is stored and encapsulated within that class.
Have a look at the changes I made and see if the function now works as you intended. Cheers!
class fibonacci_closure():
def __init__(self):
self.n = 0
def fibonaci(self):
if self.n == 0:
self.n+=1
print(0)
elif self.n == 1 or self.n == 2:
self.n+=1
print(1)
else:
i = 1
j = 1
tmp = 1
hold = self.n
while hold != 2:
hold -=1
tmp = i
i = j + i
j = tmp
self.n+=1
print(i)

Related

How incrementor function is not incrementing the num variable?

I am unable to understand please help me with same. I just want to know why num variable is not incrementing on calling a function incrementor? i guess output should be (100,100), Instead it is showing (100,0)
def main():
counter=Counter()
num=0
for x in range(0,100):
incrementor(counter,num)
return (counter.count, num)
def incrementor(c, num):
c.count+=1
num+=1
class Counter:
def __init__(self):
self.count=0
print(main())
When you have code like this:
class Counter:
def __init__(self):
self.count = 0
def incrementor(c, num):
c.count += 1
num += 1
def main():
counter = Counter()
num = 0
incrementor(counter, num)
return (counter.count, num)
print(main())
What is actually happening at the call site: incrementor(counter, num) is this:
WARNING: PSEUDO CODE AHEAD
counter = Counter()
num = 0
c = counter
num = num
call incrementor
The above is bizarre and easy to misunderstand, so I'll rephrase it:
WARNING: PSEUDO CODE AHEAD
def incrementor(c, n):
c.count += 1
n += 1
counter = Counter()
num = 0
c = counter
n = num
call incrementor
Now where I have put n = num the n is the name of the variable used inside incrementor(), which shows n is a different variable, which gets incremented inside the function, but thrown away when it returns.
So, in order to do what it seems you want to do you need to do this:
class Counter:
def __init__(self):
self.count = 0
def incrementor(c, num):
c.count += 1
return num + 1
def main():
counter = Counter()
num = 0
for x in range(0, 100):
num = incrementor(counter, num)
return (counter.count, num)
print(main())
Output:
(100, 100)

Python: pop() returning py list, not my object

I'm trying to code an exercise to solve the Queen Puzzle (yes, typical, I know) on Python. I've made a class called Queens for board state that takes in the length of each side and the list of queens, if any.
In the main program, I have a list of Queens called frontier, which is then popped one by one. However, the result I get from popping seems to be of type list, and not Queens as expected!
What is causing this, and how do I fix it?
Code snippet:
from queens import Queens
def search(n, debug=False, max=6):
frontier = [Queens(n, [])] # queue of states to explore
while frontier != []:
check = frontier.pop()
print(type(check))
if debug:
print(str(numSolutions) + " | Checking:")
print(check)
v = check.validate()
# EDIT: added more of the code; problem seems to arise here
if v == 0:
if debug:
print("Solution!")
numSolutions += 1
if n <= max:
solutions.append(check)
elif v > 0:
if debug:
print(str(v) + " more")
frontier.append(check.branch())
else:
if debug:
print("Invalid state")
pass
expected output:
<class 'queens.Queens'>
actual output:
<class 'queens.Queens'>
<class 'list'>
(yes, the one type statement printed 2 lines)
EDIT: Since there seems to be no problem with the main code, here's the file in which I defined the class:
import array
import copy
class Queens:
__slots__ = ["n", "qlist"]
def __init__(self, n, qa=None):
self.n = n # store for print function
if qa == None:
self.qlist = array.array("h")
elif type(qa) == list:
self.qlist = array.array("h", qa)
else:
assert type(qa) == array.array
self.qlist = qa # list of positions for each line
def __str__(self):
out = ""
for q in range(self.n):
if q == 0:
out += "|"
else:
out += "\n|"
for space in range(self.n):
if q < len(self.qlist) and space == self.qlist[q]:
out += "Q|"
else:
out += " |"
return out
def branch(self):
out = []
for x in range(self.n):
if x not in self.qlist:
qlist = copy.deepcopy(self.qlist)
qlist.append(x)
out.append(Queens(self.n, qlist))
return out
def validate(self):
for y in range(len(self.qlist)):
# don't need to check horizontal;
# data structure doesn't let you place them
# don't need to check vertical;
# branching eliminates those
# check diagonals
for y2 in range(len(self.qlist)):
if y != y2:
expected = self.qlist[y] - y + y2
if 0 <= expected < self.n and self.qlist[y2] == expected:
return -1
expected = self.qlist[y] + y - y2
if 0 <= expected < self.n and self.qlist[y2] == expected:
return -1
return self.n - len(self.qlist)
if __name__ == "__main__":
q = Queens(4)
print(q.validate())
q = Queens(4, [0, 1, 2])
print(q.validate())
I've figured it out. The problem happened only after frontier.append(check.branch()). branch() returns a list of queens. I thought I was appending several queens to frontier, but I was, in fact, appending a list of queens to frontier. Changing append to extend solved the issue.
When you append to your frontier the result of .branch(..) and you re-iterate you get an array back (list). Which is being printed after the loop continues to the next step.
def branch(self):
out = []
for x in range(self.n):
if x not in self.qlist:
qlist = copy.deepcopy(self.qlist)
qlist.append(x)
out.append(Queens(self.n, qlist))
return out

trying to compare two lists or one list with the same

import random
b=[]
o=[]
v=0
g=2
y=0
V=0
q=0
compat=0
alex=[]
zach=[]
while v != 5:
name="name"
position="position"
answers=[]
for i in range(10):
answer=random.randint(1,4)
answers.append(answer)
b.append(name)
b.append(position)
b.append(answers)
v+=1
print(b)
for ii in range(0,5):
t=b[g]
o.append(t)
g+=3
l=len(o)
for iii in list(o):
C = o[y]
y = y + 1
alex = []
for iiii in range(5):
I = 0
compat=0
R=o[q]
V=0
Y = C[V]
for iiiii in range(10):
r=R[I]
if r == Y:
compat+=1
else:
compat=compat
I+=1
V += 1
print(compat)
alex.append(compat)
print(alex)
zach.append(alex)
q+=1
w=len(zach)
print(zach)
print(w)
this is my code and it works pretty well. but it should put every single value against every other one but it doesnt it just put the same Y value and does not change. i have put v+=1 in tons of different places and moved around the a couple variable but it doesnt change. there should be 25 different answers for 5 people but it doesnt it just prints the same number 5 times then restarts.
any help would be appreciared
Edit: this is what i will intergrat the code above into
global compatability
import sqlite3
with sqlite3.connect("Questionare.db") as db:
cursor = db.cursor()
class mentee: # these classes are made to create a place where atributes can be filled with variables
def __init__(self,mentee_name,mentee_position):
self._mentee_posisition=mentee_position
self._mentee_name=mentee_name
def menteereport(self):
return{"mentee name:":self._mentee_name,"mentee position":self._mentee_posisition}
class mentor:
def __init__(self,mentor_name,mentor_position):
self._mentor_position=mentor_position
self._mentor_name=mentor_name
def mentorreport(self): # these are methods and they use a function with the variables instanciated within the class to make this appen
return {"mentor name":self._mentor_name,"mentor position":self._mentor_position}
class calculation:
def __init__(self,number_of_questions,compatability,mentoranswers,menteeanwers):
self._question_number= 1
self._number_of_questions=number_of_questions
self._compatability=compatability
self._mentor_values=mentoranswers
self._mentee_values=menteeanwers
def calc(self):
compat=0
c=0
for i in range(0,self._number_of_questions):
if self._mentee_values[c] == self._mentor_answers[c]:
compat += 1
c+=1
else:
compat += 0
c+=0
compatability=compat/self._number_of_questions
self._compatability=compatability
compatability=compatability*100
print(self._mentee_answers)
print(self._mentor_answers)
print("\n{:0.2f}%.\n".format(compatability))
def mentoranswer(self):
self._number_of_questions = int(self._number_of_questions)
self._question_number=1
for i in range(0,self._number_of_questions):
answer=input("Q{}".format(self._question_number))
self._question_number+=1
self._mentor_answers.append(answer)
def menteeanswer(self):
self._number_of_questions = int(self._number_of_questions)
self._question_number=1
for i in range(0,self._number_of_questions):
answer=input("Q{}".format(self._question_number))
self._question_number+=1
self._mentee_answers.append(answer)
class timerequirements:
def __init__(self,mentor_time_allotment,mentee_time_allotment,ideal_length_of_mentoring,ideal_length_of_being_mentored):
self._mentor_time_allotment=mentor_time_allotment
self._mentee_time_allotment=mentee_time_allotment
self._ideal_length_of_mentoring=ideal_length_of_mentoring
self._ideal_length_of_being_mentored=ideal_length_of_being_mentored
def main(): # this function is created to put the variables into the artibutes so that everything will work.
v = True
mentoranswers = []
menteeanswers = []
no_of_q = int(input("numebr of questions"))
while v == True:
morm = input("are your a mentor or a mentee")
if morm.lower() == "mentor":
name = input("name")
position = input("position")
answers = []
for i in range(0, no_of_q):
answer = int(input("1 or 2"))
answers.append(answer)
mentoranswers.append(name)
mentoranswers.append(position)
mentoranswers.append(answers)
print(mentoranswers)
elif morm.lower() == "mentee":
name = input("name")
position = input("position")
answers = []
for i in range(0, no_of_q):
answer = int(input("1 or 2"))
answers.append(answer)
menteeanswers.append(name)
mentoranswers.append(position)
menteeanswers.append(answers)
print(menteeanswers)
elif morm.lower() == "q":
v = False
else:
print("try again")
print(mentoranswers.mentorreport())
print(menteeanswers.menteereport())
main()
you are adding way too much noise.
for iii in list(o):
C = o[y]
y = y + 1
why don't you simply use the variable you just created? it will be incremented automatically
for iii in list(o):
C = o[iii]
you should learn how to use a loop and a few other basics. there are good tutorials on the official python site. here the for-loop one. most of your variables exist just to repeat what you are already doing.
i've avoided some high-level constructs, but i left zip.
import random
mentees = []
names = ['zach', 'alex', 'fred', 'jane', 'sara']
for name in names:
mentee = dict()
mentee['name'] = name
mentee['compatibility'] = []
answers = []
for i in range(10):
answers.append(random.randint(1,4))
mentee['answers'] = answers
mentees.append(mentee)
for mentee1 in mentees:
m1_answers = mentee1['answers']
for mentee2 in mentees:
m2_answers = mentee2['answers']
compat = 0
# zip fuses both lists into one
for m1_answer, m2_answer in zip(m1_answers, m2_answers):
if m1_answer == m2_answer:
compat += 1
mentee1['compatibility'].append((mentee2['name'], compat))
print(mentees)

Keep getting type error with decorative function

I keep getting a type error for this. I am experimenting with decorative functions. Any help is appreciated
def primer(func):
def primes(n):
print (n)
return None
#primer
def find_prime(n):
while True:
count = 2
if (count == n):
z = ("PRIME")
return z
elif (n % count == 0):
z = n / count
return z
else:
count += 1
continue
prime = find_prime()
prime(10)
def primer(func):
def primes(n):
print(n)
#return None: dont know why this is here, you could do without it
return primes
#The nontype error is occuring because your code is returning none
#so to fix that all you have to do is return the inner function
#primer
def find_prime(n):
while True:
count = 2
if (count == n):
z = ("PRIME")
return z
elif (n % count == 0):
z = n / count
return z
else:
count += 1
continue
prime = find_prime
# if you want to turn a function into a variable you have to make sure it's
# callable, which means no parantheses around it
prime(15) # then you can call it

Why is the code (Python) giving error?

import numpy as np
import matplotlib.pyplot as plt
class Prisoners_Dilemma:
def __init__(self,n,p):
self.n = n
self.p = p
def decision_array(self):
self.dict_dict = {}
for i in range(1,self.n + 1):
self.dict_dict[i] = []
list_list = []
for j in range(1,self.n):
#np.random.seed(j)
self.r = np.random.uniform(0,1)
if self.r > self.p:
q = 0
else:
q = 1
list_list.append(q)
self.dict_dict[i] = list_list
return self.dict_dict
def payoff(self):
self.dict_dict_2 = {}
for i in range(1,self.n + 1):
self.dict_dict_2[i] = []
list_list_2 = []
list_list_3=[]
for j in range(1, i):
list_list_2.append(self.dict_dict[j][i-2])
for j in range(i + 1, self.n + 1):
list_list_2.append(self.dict_dict[j][i-1])
list_list_2_np = np.array(list_list_2)
against_i = np.sum(list_list_2_np)
for_i = np.sum(self.dict_dict[i])
if against_i == 0 and for_i == 0:
payoff_i = 2
elif against_i == 0 and for_i != 0:
payoff_i = 5
elif against_i != 0 and for_i == 0:
payoff_i = -5
else:
payoff_i = -2
list_list_3.append(payoff_i)
self.dict_dict_2[i]=list_list_3
return self.dict_dict_2
def gameplay(self, N, initial_count):
self.counter = initial_count
for i in range(N):
for j in range(1, self.n + 1):
z = self.dict_dict_2[j]
x = np.array(z)
self.counter += np.sum(z)
return self.counter
y = Prisoners_Dilemma(15,0.015)
print (y.gameplay(20,100))
In the above code, the compiler gives the error that instance has no attribute as dict_dict_2 even though its prefixed with self. Moreover, it is perfectly fine with dict_dict. For the sake of completeness I have included the whole code but the problem lies only in payoff and gameplay methods?
dict_dict_2 is only created in payoff(), therefore you must call it before attempting to call gameplay().
The issue is that you are only creating self.dict_dict_2 variable in the payoff function, but in your logic where you are calling gameplay() function , you are not calling the payoff() function before accessing dict_dict_2 , from the looks of it you are not calling that function anywhere at all.
Not sure what dict_dict_2 holds, but the above is the reason why you are getting the issue, maybe you can move the initialization part of dict_dict_2 to __init__() function , though that would not fix the complete issue, since you would still be trying to access dict_dict_1[j] which can error out if j is not a key in dict_dict_2 .

Categories