Why is the code (Python) giving error? - python

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 .

Related

local variable 'n' referenced before assignment. Closures

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)

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

Python error: int object has no attribute to append?

I can't figure out why my code isn't working, very frustrating. I constantly get the error: int object has no attribute to append (for average.append(i, average//250)). But I can't figure out what exactly is wrong here. Is it not possible to import other definition in append functions?
I hope somebody can help me out!
Any help with my code in general is appreciated :)
def main():
average = []
y_values = []
for x in range(0, 2501, 500):
for i in range(250):
average.append(calculate(x))
average = sum(average)
print("{} euro, {} worpen".format(i, average//250))
y_values.append(average//250)
x_values = [0, 500, 1000, 1500, 2000, 2500]
y_values = []
plt.plot(x_values, y_values)
plt.xlabel("Startgeld")
plt.ylabel("Aantal worpen")
plt.title("Monopoly")
plt.show()
def calculate(game_money):
piece = monopoly.Piece()
board = monopoly.Board()
owns = possession(board)
dice = throw()
throw_count = 0
number = 0
total_throw = 0
while not all(owns.values()):
number == throw()
piece.move(number)
total_throw = total_throw + number
throw_count += 1
if total_throw > 40:
game_money += 200
elif board.values[piece.location] > 0:
if game_money > board.values[piece.location]:
if owns[board.names[piece.location]] == False:
owns[board.names[piece.location]] = True
game_money = game_money - board.values[piece.location]
return total_throw
def throw():
dice = randint(1,6) + randint(1,6)
return dice
def possession(board):
owns = {}
for i in range(40):
if board.values[i] > 0:
owns[board.names[i]] = False
return owns
if __name__ == "__main__":
main()
You done a small mistake in your code. See my comment below and correct your code accordingly. Good Luck :-)
y_values = []
average = []
for x in range(0, 2501, 500):
for i in range(250):
average.append(calculate(x))
#average = sum(average) #This is your mistake. Now onward average will be considered as int object make it like below
average1 = sum(average)
print("{} euro, {} worpen".format(i, average1//250))
y_values.append(average1//250)

Categories