Python Forum
function with 'self' input parameter errors out with and without 'self' called - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: function with 'self' input parameter errors out with and without 'self' called (/thread-36068.html)

Pages: 1 2


function with 'self' input parameter errors out with and without 'self' called - dford - Jan-14-2022

Hi,

I've got something that just cropped up. This is not a tkinter question, though I'm using tkinter in the app. I've got some functions that are called from some tkinter objects, so I had to define them with 'self' as an input parameter, as the code was requiring that.

Except, when I'm trying to call the function from within another function, it gives me an error if I include 'self', and gives me an error if I exclude 'self'.

Here is the function definition. I should also stipulate that this is not defined within a class:

def updateMainTasks(self):
    global mydict
   

    cnxn= sqlite3.connect(sqlFileLoc)
    mydict, data = getCboMainTaskList()

    #try is to catch that mydict-key.get value exception when it is null
    try:
        #compensating for when Headline is not filled in yet.
        if HeadlineMainTask.get()== '':
            thisTask =cboMainTask.get()
        elif HeadlineMainTask.get() != cboMainTask.get():
            thisTask=HeadlineMainTask.get()
        else: thisTask = cboMainTask.get()

        if cboMainTask.get().__len__() !=0:
            sql='Select TaskID, Headline, Requester, Headline, Explanation,RequestDate, \
                Complete, Acknowledged,DueDate from MainTasks \
                where TaskID = ' + str(mydict[thisTask]) 

            df=pd.read_sql_query(sql, cnxn)
    
            
    
            #clear then fill cboTask
            cboMainTask['values']=list(mydict)
            
            #thiscur.close()
    
            #Requester
            RequesterMainTask.delete(0,'end')
            try:
                RequesterMainTask.insert(0,df.iat[0,2])
            except:
                pass
    
            #Headline
            HeadlineMainTask.delete(0,'end')
            HeadlineMainTask.insert(0,df.iat[0,3])
        
            #Explanation
            ExplanationMainTask.delete('1.0','end')
            ExplanationMainTask.insert('1.0',df.iat[0,4])
        
            #Request Date
            RequestDateMainTask.delete(0,'end')
            try:
                RequestDateMainTask.insert(0,df.iat[0,5])
            except:
                pass
    
            #Due Date
            DueDateMainTask.delete(0,'end')
            try:
                DueDateMainTask.insert(0,df.iat[0,8])
            except:
                pass
    
            #Complete
        
            if df.iat[0,6]=='1':
                ChkButtonCompleteMainTask.select()
            else:
                ChkButtonCompleteMainTask.deselect()
    
            #Acknowledged
            if df.iat[0,7]== '1':
                ChkButtonAcknowledgedMainTask.select()
            else:
                ChkButtonAcknowledgedMainTask.deselect()
        
    
            #filter down cboTaskSteps
            cboTaskStep.set('')

            sql2="Select StepDescription, TaskStepID \
                from TaskSteps where TaskID = " + str(mydict[thisTask]) 
            thiscur=cnxn.cursor()
            thiscur.execute(sql2)
            cnxn.commit()
            mydict=dict(thiscur.fetchall())
            data = list(mydict.keys())
            cboTaskStep['values']=list(mydict)
            if mydict.__len__() > 0:
                cboTaskStep.current(0)
                
            #update taskStepList
            taskStepList.delete(0,'end')
            for c in list(mydict):
                taskStepList.insert('end',c)
            
            #filter down cboSubTasks
            #print(str(mydict[cboTaskStep.get()]))
            cboSubTasks.set('')
            #If no record, don't do it.
            if mydict.__len__()> 0:
                sql2="Select StepDescription, SubTaskStepID \
                from SubTasks where TaskStepID = " + str(mydict[cboTaskStep.get()]) 
                thiscur=cnxn.cursor()
                thiscur.execute(sql2)
                cnxn.commit()
                mydict=dict(thiscur.fetchall())
                data = list(mydict.keys())
                cboSubTasks['values']=list(mydict)
            if mydict.__len__() > 0:
                cboSubTasks.current(0) 
                
        #clears the screen when you hit the clear button
        else:
            
            sql='Select TaskID, Headline, Requester, Headline, Explanation,RequestDate, \
                Complete, Acknowledged,DueDate from MainTasks \
                where TaskID is null' 
            RequesterMainTask.delete(0,'end')
            HeadlineMainTask.delete(0,'end')
            ExplanationMainTask.delete('1.0','end')
            RequestDateMainTask.delete(0,'end')
            DueDateMainTask.delete(0,'end')
            ChkButtonCompleteMainTask.deselect()
            ChkButtonAcknowledgedMainTask.deselect()
    
        cnxn.close()
    
        #unset dirty flag on Save button
        btnsaveMainTasks.config(bg="silver")
    
        #update history of selections at top of screen
        displayHistory()
    except:
        pass
    
    return
Here is the code from where it is being called, down towards the bottom. I can't include the whole program as it is too extensive.

def saveMainTasks():
    #saves dirty fields to database
    
    global ChkComplete1
    global ChkAcknowledged1
    global mydict
    mydict, data = getCboTaskList()
    #Try to save an existing record with a TaskID
    if cboTask.get() != '':
        sql="Update MainTasks set \
            Requester = '" + RequesterMainTask.get() + "', \
            Headline = '" + HeadlineMainTask.get() + "', \
            Explanation= '" + ExplanationMainTask.get('1.0','end') + "', \
            RequestDate= '" + RequestDateMainTask.get() + "', \
            DueDate= '" + DueDateMainTask.get() + "', \
            Complete = '" + str(ChkComplete1.get()) + "', \
            Acknowledged= '" + str(ChkAcknowledged1.get()) +"' \
        Where TaskID = " + str(mydict[cboTask.get()])
    #If that fails, try to add a new record
    else:
        sql="Insert into MainTasks (Requester, Headline, Explanation, RequestDate, DueDate, Complete, Acknowledged) \
        Values('" +RequesterMainTask.get()+ "', '" + HeadlineMainTask.get()+ "', '" + ExplanationMainTask.get('1.0','end') + "', '"+ RequestDateMainTask.get() + "', ' \
         " + DueDateMainTask.get()+ "', '" + str(ChkComplete1.get()) + "','" + str(ChkAcknowledged1.get()) + "')"


    cnxn= sqlite3.connect(sqlFileLoc)
    c=cnxn.cursor()
   
    c.execute(sql)
    cnxn.commit()
      
    #refresh combo box after delete
    c.execute('Select Headline, TaskID  from MainTasks')
    cnxn.commit()
    mydict=dict(c.fetchall())
    data = list(mydict.keys())
    
    updateMainTasks()
    
    #don't add key reference again.  only one works.
    cboTask.config(values=data)
    
    c.close()
    cnxn.close()
    btnsaveMainTasks.config(bg="silver")
This is also where that updateMainTasks function is being called, from a widget. This is where I think it is requiring me to use 'self', even though it does not call it with a parameter at this point.
btnRefreshMainTask = tk.Button(maintaskframe, command=updateMainTasks, text = "Refresh", bg="silver")
btnRefreshMainTask.place(x=col2+240, y=y7, width=60)
The error I get if I don't call it with the 'self' parameter is:

Output:
updateMainTasks() missing 1 required positional argument: 'self'
The error I get when I do call with 'self' is:

Output:
name 'self' is not defined
Thing is, the was working previously, and I don't know what change caused it to break. Any ideas appreciated. I'm finding the constraints imposed by tkinter a little exasperating.


RE: function with 'self' input parameter errors out with and without 'self' called - Yoriz - Jan-14-2022

More information is needed, where and how is this being used.
You need to show more code.


RE: function with 'self' input parameter errors out with and without 'self' called - dford - Jan-14-2022

Thanks Yoriz. I've updated my original post to show the function from where it is being called.


RE: function with 'self' input parameter errors out with and without 'self' called - Yoriz - Jan-14-2022

Sorry but the code you have shown is pretty irrelevant to the problem at hand, maybe I asked for the wrong thing.
can you show the definition of updateMainTasks()
You are using self which is normally used with a class but it doesn't look like you are using classes.
by your error it seems like you have a function that is defined as follows
def updateMainTasks(self):
    ....
what is it that you actually need to pass into the function, if you don't need to pass in anything you can remove the self parameter from the definition.


RE: function with 'self' input parameter errors out with and without 'self' called - dford - Jan-14-2022

Sorry. You asked for something about when and where it was being used, and that's how I interpreted it. I've updated the top post to include the function definition. Hope that helps.


RE: function with 'self' input parameter errors out with and without 'self' called - Yoriz - Jan-14-2022

def updateMainTasks(self):
This is a function not a method of a class, self is not required and you do not use self anywhere inside the function it can be removed.
def updateMainTasks():



RE: function with 'self' input parameter errors out with and without 'self' called - dford - Jan-15-2022

Yes, logic would tell me that. However, that is not what I was running into. The interpreter was blowing up no matter what I did.

I did the following, in an attempt to use one function ( updateMainTasksWrapper) to be called from the widget, and the main function to be called from within other functions. It seems to be working at the moment. WHY, I have no idea. I've tried to find the website again where it says that the widget will tack on an unseen 'self' when it makes its call, but I can't find it. I think it was in a reply on a stack overflow question. I'd have to try to remember the exact phrase I was searching on when I found that.

def updateMainTasksWrapper():
    updateMainTasks()


#======================================================================

def updateMainTasks():
    cnxn= sqlite3.connect(sqlFileLoc)
    mydict, data = getCboMainTaskList()
    ......



RE: function with 'self' input parameter errors out with and without 'self' called - deanhystad - Jan-15-2022

"self" is used to accept the instance argument in an instance method call just as "cls" is used to accept the class argument for a class method. The words "self" and "cls" are conventions and the arguments could be named anything, but it is best to follow conventions.

In Python you call an instance method like this "instance.method(args)" where "instance" is an instance of a class, "method" the name of the instance method, and args are whatever additional arguments are passed. Python converts this to "class.method(instance, args)" prepending the instance as the first argument to the method call. The instance argument becomes "self" inside the body of the method.

I think "update_main_tasks()" is a function, not a method and it should not have a "self" argument. When you bind this function to a tkinter widget, the function gets called with an argument, probably a tuple containing information about the event that caused the function to be called. You should find out what this information is. If you don't need the information you should modify the binding to not pass the argument. This is easily done using a lambda expression.
button = tk.Button(root, command=lambda event:update_main_tasks())



RE: function with 'self' input parameter errors out with and without 'self' called - Yoriz - Jan-15-2022

If it's the case that you have an event handler that when called takes an event parameter but you want to be able to call it yourself and also have no need to use the event parameter just give it a default of None.
def updateMainTasks(event=None):



RE: function with 'self' input parameter errors out with and without 'self' called - dford - Jan-15-2022

(Jan-15-2022, 01:26 PM)deanhystad Wrote: command=lambda event:update_main_tasks()

This seems to be working, on an initial try. Thanks deanhystad. My first time trying a lambda. I was lamenting the corner I was painted into with the other way not allowing any function parameters. I'll experiment more with this. Again, thanks.