Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: function takes 1 positional argument but 2 were given, how?

I was creating a Sudoku Game in python with Tk.

I got a error about the function on a keypress for a button

from random import randint
from tkinter import *

class sudoku:
    global root,result,lb
    def __init__(self):
        self.aleatoriedade()
        for k in range(9):
            j=randint(0,80)
            x=j//9
            y=j-(x*9)
            lb[x][y]['text']=result[x][y]
        lb[0][0].bind('<KeyPress-2>',self.kk)
        #setted this for test
        root.mainloop()

    def kk(self):
        lb[0][0]['text']='2'


    def aleatoriedade(self):
        for i in range(9):
            var=0
            while var in result[0]:
                var=randint(1,9)
            result[0][i]=var

        for i in range(1,9):
            for j in range(9):
                result[i][j]=result[0][field[i][j]-1]

#MAIN()
n = 3
field = [[(i*n + i//n + j) % (n*n) + 1 for j in range(9)]for i in range(9)] 
result = [[None for i in range(9)]for i in range(9)]
lb=[[None for i in range(9)]for i in range(9)]
x=0
y=0
root=Tk()

for i in range(9):
    for j in range(9):
        lb[i][j]=Button(root,font=("Verdana",'13',"bold"),bd=1,height=3,width=6)
        if (i in (0,1,2,6,7,8) and j in (0,1,2,6,7,8))or(i in (3,4,5) and j in (3,4,5)):
            lb[i][j]['bg']='white'
        lb[i][j].grid(row=i,column=j)
janela=sudoku()

and this error/exception in lb[0][0].bind('<KeyPress-2>',self.kk)

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python33\lib\tkinter\__init__.py", line 1489, in __call__
    return self.func(*args)
TypeError: kk() takes 1 positional argument but 2 were given

I don't mind where is the error. I have included the self on my function

like image 543
648trindade Avatar asked May 24 '14 08:05

648trindade


Video Answer


1 Answers

I see that this has been answered, but I have a way I really prefer and that you and others may appreciate.

Say that your method kk is used in multiple spots, and you don't want to have to send in some random variable to take up the spot of "another_parameter" shown below (working off of Christian's response),

def kk(self, another_parameter):

Personally, I think parameter lists should have ONLY what they need. So, as long as you have no need for the "another_parameter" variable that the bind() function sends, I suggest using Lambda by doing the following:

lb[0][0].bind('<KeyPress-2>',lambda e:self.kk())

I think you need the two parentheses after kk now because lambda is actually going to run that function with it's parameters (in your case, if you remove the one I said to, there would be none). What lambda is doing for us is catching the parameter being thrown to kk from the bind function (that is what the 'e' is after lambda, it represents the argument). Now, we don't need it in our parameter list, and we can resume our kk definition to be

def kk(self):

I started using the approach by Christian (which works!) but I didn't like the extra variable. Obviously both methods work, but I think this one helps, especially if the function being called in bind is used more than once and not necessarily used by a bind call.

like image 138
gnasr Avatar answered Oct 05 '22 16:10

gnasr