I'm having a difficulty implementing functions in the class ArrayQ. The task is to create a class and have three methods in it, enqueue, dequeue and isEmpty. In "self.array.append(self.array)" I'm not really sure if it's supposed to be array,self.array,self or something else in the parenthesis. The basictest() function below was given to us to controll that our class works, and it doesn't at the moment.
from array import array
class ArrayQ:
def __init__(self,array):
self.array = array
def enqueue(self):
self.array.append(self.array)
def dequeue(self):
self.array.pop(0)
def isEmpty(self):
if not self.array:
print("queue is empty")
#print(ArrayQ)
lista = []
def basictest():
q = ArrayQ(lista)
q.enqueue(1)
q.enqueue(2)
x = q.dequeue()
y = q.dequeue()
if (x == 1 and y == 2):
print("test OK")
else:
print("FAILED expexted x=1 and y=2 but got x =", x, " y =", y)
basictest()
I get the following error message:
Traceback (most recent call last):
File "d1.py", line 31, in <module>
basictest()
File "d1.py", line 22, in basictest
q.enqueue(1)
TypeError: enqueue() takes 1 positional
argument but 2 were given
So could anybody please guide me towards how I should solve this problem so I could make this code work? Among the presumably several errors in this code, why can't I use "q.enqueue(1)" to alter my list using the function, or method, written in the class?
Your problem is here.
def enqueue(self):
self.array.append(self.array)
This method takes one param: self. It's a reference of that object, so, unless you've got a classmethod your class methods must have a self param as first parameter.
Now, your basictest() function calls a q.enqueue(1) but your object q is a ArrayQ and its enqueue function has only one parameter: self. It's implicitly, you cannot use 1 as self.
So, edit enqueue in this way:
def enqueue(self, value):
self.array.append(value)
First of all, there is an incorrect indentation in the class "ArrayQ". And second, there is only one default argument is passed in the "enqueue" method definition. When you create an instance of an object, the object itself is passed as a default argument(self). In "q.enqueue(1)" you are actually passing two parameters, first is self and the second is "1".
Related
I'm relatively new in programming with Python. This code was working perfectly, until I tried turning it into a class.
I'm making a class for my sudoku solver code, to practice classes and dabbling my toes in object oriented programming.
So I have read a whole bunch of questions from users who have a similar problem, most answers were :
-instantiate class first before calling a function from said class
but none of them seem to work for my specific example.
Here is my class:
#assume sudoku is imported as a np.array, white spaces replaced by zeros
class Sudoku():
solution_number = 1
def __init__ (self, sud_arr):
self.sudo = sud_arr
#print(self.sudo)
def possible (self, y, x, num):
for i in range(9):
if self.sudo[y][i] == num:
return False
if self.sudo[i][x] == num:
return False
yy = (y//3)*3
xx = (x//3)*3
for i in range(3):
for j in range(3):
if self.sudo[yy+i][xx+j] == num:
return False
return True
def solve(self):
for i in range(9):
for j in range(9):
if self.sudo[i][j] == 0:
for nr in range(1,10):
if Sudoku.possible(i,j,nr): #line 34
self.sudo[i][j] = nr
Sudoku.solve()
self.sudo[i][j] = 0
return
if Sudoku.solution_number > 1: #if there is more than one solution, include solution number
print("Solution Number {}".format(Sudoku.solution_number))
else: print("Solution Number 1")
print(self.sudo)
Sudoku.add_sol_num()
#classmethod
def add_sol_num(cls):
cls.solution_number += 1
After running:
s = Sudoku(su) #where su is a numpy array sudoku
s.solve() #line 52
I get the error:
File "/Users/georgesvanheerden/Python/Projects/Sudoku/SudokuSolver.py", line 52, in <module>
s.solve()
File "/Users/georgesvanheerden/Python/Projects/Sudoku/SudokuSolver.py", line 34, in solve
if Sudoku.possible(i,j,nr):
TypeError: possible() missing 1 required positional argument: 'num'
[Finished in 1.9s with exit code 1]
Sorry if this is too much code, I didn't know which parts to cut out.
use self.possible when using a method, Sudoku.possible gets you a reference to that method that cant find the instance that you are calling it from.
That also applies to if Sudoku.solution_number > 1, generally the pythonic way is to use the self variable, or the first argument to the method (although you can also pass self to the function: Solution.possible(self, i, j , nr) )
So your code would look like:
def solve(self):
for i in range(9):
for j in range(9):
if self.sudo[i][j] == 0:
for nr in range(1,10):
if self.possible(i,j,nr): #line 34
self.sudo[i][j] = nr
self.solve()
self.sudo[i][j] = 0
return
if self.solution_number > 1: #if there is more than one solution, include solution number
print("Solution Number {}".format(self.solution_number))
else: print("Solution Number 1")
print(self.sudo)
Sudoku.add_sol_num() # add_sol_num is a #classmethod
you can add self as the first argument:
if Sudoku.possible(self, i, j, nr): #line 34
Let us first understand the error that is being given :
TypeError: possible() missing 1 required positional argument: 'num'
This says that there is no value for num argument while calling possible() method.
But you are passing 3 arguments here :
if Sudoku.possible(i,j,nr)
So what went wrong here ???
If you see the definition of your method:
def possible (self, y, x, num):
This says that you will be passing 4 arguments and one of which would be the instance/object of the class (self argument).
1. If we invoke this method using a class object, `self` argument is passed by default. So in this case we can just send 3 arguments apart from `self`.
2. If you want to invoke this method like you have done above, you will have to provide a value for `self` argument explicitally.
So, here is how you can do it (pythonic way and good approach) :
While invoking the method possible, use self keyword.
if self.possible(i,j,nr):
In lines 34 and 36 you call two methods as if they are static methods since you call the methods on the class not on some instance. That also is the reason, why self is not recognized and hence asked for another parameter in the method call.
You want to call the methods of the current instance of Sudoku. Therefore
if self.possible(i,j,nr):
in line 34 and
self.solve()
in line 36 should do the trick.
As an example I have a function f and a variable a=1.
Sometimes f needs a and I want to call f(a=a) and other times f has no arguments. How can I deal with that?
When I try to call f(a=a) (expecting that it will silently ignore the case where a is not used in f), I get the following TypeError:
f got an unexpected keyword argument 'a'
Edit
I want to implement a function g such that, given:
def f1(a):
return a
def f2():
return 1
we have:
g(f1, a) == a
g(f2, a) == 1
It seems you want to inspect a function's arguments.
For that, use the inspect module:
import inspect
def g(somefunc, *params):
num_args = len(inspect.getargspec(somefunc).args)
return somefunc(*params[:num_args])
Testing, with your functions:
def f1(a):
return a
def f2():
return 1
>>> print(g(f1, 3))
3
>>> print(g(f2, 3))
1
use keyword dictionary in f:
def f(**kwargs):
if 'a' in kwargs:
print("a passed with value {}".format(kwargs['a']))
else:
print('a not passed')
f(a=12)
f()
prints:
a passed with value 12
a not passed
it makes argument testing/retrieving completely manual. You can do anything you want, and it can be generalized to several arguments.
This also forbids to pass arguments as positional like f(12) which is probably a good thing in your case.
>>> f(12)
Traceback (most recent call last):
TypeError: f() takes 0 positional arguments but 1 was given
The drawback is that the caller cannot rely on parameter names to know what to pass. Either create a docstring, or people will have to read the code/guess...
Now to apply that to your edit, which kind of changes the problem I must say. So f2 cannot be changed, in that cas the work must be done in the wrapper function:
def f1(a):
return a
def f2():
return 1
def g(f,arg):
try:
return f(a=arg)
except TypeError:
return f()
a=12
print(g(f1, a))
print(g(f2, a))
prints:
12
1
so "better ask forgiveness than permission": if we get a TypeError (raised when the parameter isn't known by the function), we just call the function without the parameter. The drawback if that if the first function returns a TypeError, we cannot know if it was the parameters or inside the function.
A workaround would be to inspect the error message and only call the function without parameters if the error message is about parameters:
def g(f,arg):
try:
return f(a=arg)
except TypeError as e:
if "unexpected keyword" in str(e):
return f()
else:
raise e # another TypeError, let it pass
Simply specify the default argument in the function def line...
def f(a=1):
return(a)
print(f()) #returns 1
print(f(a = 2)) #returns 2
For your next part (as you seemed to have switched your question with edits...
def g(f, a):
return(f(a))
As a way of practicing python I'm trying to write a little program that creates sudoku puzzles. I've found multiple questions similar to my issue but none seem to exactly relate.
#!usr/bin/python3
from random import randint
class Puzzle :
def __init__(self, **puzzle):
puzzle = [[0 for x in range(9)]for y in range(9)]
def createEasy(self):
count = 0
while(count < 32):
i = randint(0,8)
j = randint(8,9)
k = randint(1,9)
if (self.puzzle[i][j] != 0):
self.puzzle[i][j] = k
count += 1
def createMedium(self):
count = 0
while(count < 30):
i = randint(0,8)
j = randint(8,9)
k = randint(1,9)
if (self.puzzle[i][j] != 0):
self.puzzle[i][j] = k
count += 1
def createHard(self):
count = 0
while(count < 26):
i = randint(0,8)
j = randint(8,9)
k = randint(1,9)
if (self.puzzle[i][j] != 0):
self.puzzle[i][j] = k
count += 1
def main():
print("Welcome to sudoku!!!")
answer = input( "what level of difficultly do you want today?")
if (answer == "easy"):
self.createEasy()
for x in Puzzle.puzzle:
for y in x:
print(y)
print('\n')
Puzzle.main()
Most answers I found either had to do with functions not being defined in the right order or not putting "self" in the parameter list of all the functions. One answer even said to get rid of "self" parameter in the init function but that didn't help either. I also found this answer though I don't think it relates either. NameError: name 'self' is not defined The only thing I can think of is that I need to declare the list called puzzle elsewhere since it's suppose to be a class variable but from python code I've I don't think that's true not to I'm not sure since it's 2d and writing puzzle = [][] is wrong.
Sorry here's the whole output with error.
Welcome to sudoku!!!
what level of difficultly do you want today?easy
Traceback (most recent call last):
File "sudoku_maker.py", line 49, in <module>
Puzzle.main()
File "sudoku_maker.py", line 43, in main
self.createEasy(self)
NameError: name 'self' is not defined
It seems like you want main() to be a class method or a static method rather than an instance method. Class methods are methods that are not bound to an object but to a class. In that case, you need to define it clearly.
https://docs.python.org/3.5/library/functions.html#classmethod
https://docs.python.org/3.5/library/functions.html#staticmethod
This answer clearly explains the difference between class methods and static methods.
What is the difference between #staticmethod and #classmethod in Python?
One more way of solving your problem is :
Make main() as an instance method by passing self as an argument.
main(self)
Create an object of Puzzle.
puzzle = Puzzle()
Call the object's main method.
puzzle.main()
The error disappears if you make the following changes:
Add self as a parameter of the main() function.
Create an instance of the class: p = Puzzle() and call p.main() then.
Write self.puzzle in the __init__ function instead of just puzzle.
(Then there are different errors though not related to this one)
First of all, in __init__ method when you declare puzzle attribute, you forgot the self, so it is not declared:
def __init__(self, **puzzle):
self.puzzle = [[0 for x in range(9)] for y in range(9)]
You also forgot de self when declaring the main function. And, inside of this one you got an error too, when you call Puzzle.puzzle, it should be with the self instance:
def main(self):
print("Welcome to sudoku!!!")
answer = input( "what level of difficultly do you want today? ")
if (answer == "easy"):
self.createEasy()
for x in self.puzzle:
for y in x:
print(y)
print('\n')
And finally, when you call the function. You need to create the instance of Puzzle first, but you are using Puzzle.main, so your not initializing the object, so the self instance will not exist.
You have to do it like this:
Puzzle().main()
However, there's another error when using randint(a, b), because this function generate a random int between a and b, but including the limits, so when you call it in createEasy, the 9 should not be in the limits.
Sorry for the title, I hope it reflects correctly my problem :
In the following code, I was expecting the result to be result 0 1 2 but instead I have 2 2 2. The code inside my_function seems to be interpreted with the last instance of obj. What is wrong ?
class Example:
def __init__(self, x):
self.x = x
def get(self):
return self.x
a_list = []
for index in range(3):
obj = Example(index)
def my_function(x):
#some stuff with x like obj.another_function(x)
return obj.get()
a_list.append(my_function)
for c in a_list:
print(c())
When you define this
def my_function():
return obj.get()
Python will understand that my_function should run the get() method of an object called obj and return the value. It won't know the value of obj and what the get() method does until you attempt to call it.
So, you are actually defining three different functions that will eventually do the same thing. And, in the end, running the same code thrice.
But why is the return 2 2 2?
Because after the last iteration, the value of obj is Example(2)* because you redefine its value at every iteration, and the last one remains.
*
because of this line obj = Example(index)
Understanding a few things about how python works will help you understand what's happening here. Here obj is a closure, closures are evaluated at call time, not when the function is defined so if I do this:
x = "hello"
def printX():
print x
x = "goodbye"
printX() # goodbye
I get "goodbye" because printX is referencing a global variable in my module, which changes after I create printX.
What you want to do is create a function with a closure that references a specific object. The functional way to do this is to create a function that returns another function:
x = "hello"
def makePrintX(a):
def printX():
# We print a, the object passed to `makePrintX`
print a
return printX
# x is evaluated here when it is still "hello"
myPrintX = makePrintX(x)
x = "goodbye"
myPrintX() # "hello"
If you're having trouble understanding the above example I would recommend reading up on python's scoping rules. For your example, you could do something like this:
class Example:
def __init__(self, x):
self.x = x
def get(self):
return self.x
def makeObjFunction(obj):
def objFunction(x):
return obj.get()
return objFunction
a_list = []
for index in range(3):
obj = Example(index)
my_function = makeObjFunction(obj)
a_list.append(my_function)
for c in a_list:
print(c("some value"))
You are appending three my_functions to the a_list which are all closures over the same Example object. Try:
def my_function():
return obj
<__main__.Example object at 0x0054EDF0>
<__main__.Example object at 0x0054EDF0>
<__main__.Example object at 0x0054EDF0>
You can see they have the same id so calling get() on each should give the same answer.
If you just append the obj.get function (and drop the my_function) it'll work fine.
a_list.append(obj.get)
....
0
1
2
Edit: You've updated your question so to let you do more stuff in my_function(). It's still basically a scoping problem.
def my_func_factory(p_obj):
def my_function(x):
#some stuff with x like obj.another_function(x)
return p_obj.get()
return my_function
for index in range(3):
obj = Example(index)
a_list.append(my_func_factory(obj))
Since my_function can't see obj being reassigned, each instance doesn't pick up the change.
I think append() during the for just append the function address in a_list[]. After for iteration, the a_list is really given the number. Then it discovers the address of my_function, and they get the number in my_function, this is, 2. That's why you get [2,2,2].
Or maybe, in my_function, function give the method of "obj". But for iteration change the "obj" memory address each time, so the symbol "obj" always aim to the newest object Example. Due to my_function always get "obj", you get the same number from the last object.
I have some Python code in below written in Python 2.7 and I have problem with calling a function form inside another function.
class CSP:
def __init__(self, matrix):
self.X = []
self.D = []
self.C = []
self.matrix = util.copyMatrix(matrix)
self.counter = 0
# Matrix to Vector
vector = [item for line in self.matrix for item in line]
chars = map(str, vector)
result = ['*' if item == '0' else item for item in chars]
def solve(self):
""" Returns the result matrix.
The sudoku matrix is self.matrix.
Use util.printMatrix in purpose of debugging if needed. """
"*** YOUR CODE HERE ***"
def init(self,result):
for i in range(9):
for j in range(1,10):
var = var_char[i]+str(j)
self.X.append(var)
domain = set([1,2,3,4,5,6,7,8,9])
self.D.append(domain)
gamelist = result
for i in range(len(gamelist)):
if(re.match("\d+",gamelist[i])):
self.D[i] = set([int(gamelist[i])])
self.set_constraints()
#########################################################################
def set_constraints(self):
for x in self.X:
for y in self.X:
if((x[0] == y[0] and x[1] != y[1]) or (x[1] == y[1] and x[0] != y[0])):
flag = True
for c in self.C:
if(x in c and y in c):
flag = False
if(flag):
self.C.append(set([x,y]))
for a in [0,3,6]:
for b in [0,3,6]:
self.set_cube_constraints(a,b)
How to call init() function in solve() and also call self.set_constraint() inside init() function?
Within function solve(), init() is a function, not a method. Therefore it can only be called in the same manner that any other unbound function can be called: by passing the correct number of arguments to it. This would work:
init(self, results)
Note that you need to explicitly pass a reference to the object in self because init() is not a method. Within solve() self refers to the CSP instance, so this should work.
However, set_constraints() is also a normal function, so you can not call it from init() with self.set_constraints(), but set_constraints(self) should work. Note that you need to declare function set_constraints() before init() otherwise you will get a "referenced before assignment" error.
Having said all that, this is just awful. Why not make init() and set_constraints() proper methods of the class?
set_constraints is not a part of the class and therefore cannot be called with self.
If you put it one level up (remove one indentation level of it) then your code should work better.
I can see that this is some kind of coding exercise and you are told to write code in one particular place. I think you may be overcomplicating the answer because what you are coding here looks very messy by design and you should probably split out your functionality a lot more if this should be considerered clean code.