You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python类中'missing 1 required positional argument'错误排查咨询

解决Tkinter+SQLite3应用中的参数错误与嵌套函数问题

问题1:missing 1 required positional argument: 'category_id' 错误

  • 核心原因1:调用Backend.insert_account_type时直接用类而非实例。实例方法必须通过类的实例调用,否则Python会把你传入的第一个参数当成self,导致参数数量不匹配。你已经创建了tb = Backend()实例,必须用它来调用方法。
  • 核心原因2:insert_account_type方法的SQL执行语句多传了self。SQL语句需要2个参数,但你传了(self, category_type, category_id)共3个,导致参数不匹配。

问题2:missing 1 required positional argument: 'self' 错误

这个错误同样是因为直接用类调用实例方法(比如Backend.view_account_type(self))。实例方法的self参数是Python自动传入的实例引用,直接用类调用时必须手动传入实例,正确做法是用已创建的tb实例调用方法。

问题3:类内嵌套函数是否需要传递self

嵌套在类方法里的闭包函数不需要定义self参数,它可以直接访问外部类方法中的self(即Frontend的实例)。你之前给display_account_types加self参数是多余的,调用时也不需要传。


修正后的完整代码

import tkinter
from tkinter import *
from tkinter import ttk
import tkinter.messagebox
import sqlite3

root = Tk()
root.title('Simple Application')
root.config(bg='SlateGrey')
root.geometry("")

# BackEnd
class Backend():
    def __init__(self):
        self.conn = sqlite3.connect('accounting.db')
        self.cur = self.conn.cursor()

        self.conn.execute("""CREATE TABLE IF NOT EXISTS account_type(
         id             INTEGER      PRIMARY KEY,
         category_type    INTEGER      NOT NULL,
         category_id      TEXT         NOT NULL
         )""")

        self.conn.commit()
        self.conn.close()

    def insert_account_type(self, category_type, category_id):
        self.conn = sqlite3.connect('accounting.db')
        self.cur = self.conn.cursor()
        # 修正:移除多余的self参数,匹配SQL需要的2个参数
        self.cur.execute("""INSERT INTO account_type(category_id, category_type) VALUES(?,?);""",
                         (category_id, category_type,))
        self.conn.commit()
        self.conn.close()

    def view_account_type(self):
        self.conn = sqlite3.connect('accounting.db')
        self.cur = self.conn.cursor()
        self.cur.execute("SELECT * FROM account_type")
        self.rows = self.cur.fetchall()
        self.conn.close()
        return self.rows

# 初始化Backend实例
tb = Backend()

# Front End
class Frontend():
    def __init__(self, master):
        # 框架布局
        self.top_frame = LabelFrame(master, bg='SlateGrey', relief=SUNKEN)
        self.top_frame.pack()

        self.bottom_frame = LabelFrame(master, bg='SlateGrey', relief=SUNKEN)
        self.bottom_frame.pack()

        self.right_frame = LabelFrame(self.top_frame, bg='SlateGrey', relief=FLAT,
                                      text='Details Entry', fg='maroon')
        self.right_frame.pack(side=RIGHT, anchor=NE)

        self.side_frame = LabelFrame(self.top_frame, bg='SlateGrey', relief=SUNKEN, text='Menu Buttons', fg='maroon')
        self.side_frame.pack(side=LEFT, anchor=NW)

        self.bot_frame = LabelFrame(self.bottom_frame, bg='Grey', relief=SUNKEN, text='Field View', fg='maroon')
        self.bot_frame.pack(side=BOTTOM, anchor=SW)

        # 侧边按钮
        self.btn1 = Button(self.side_frame,
                           text='Main Account Types',
                           bg='SteelBlue4',
                           font=('cambria', 11),
                           anchor=W,
                           fg='white',
                           width=18, height=2,
                           command=self.main_account)
        self.btn1.grid(row=0, column=0, pady=0, sticky=W)

    def main_account(self):
        # 变量定义
        self.category_type = StringVar()
        self.category_id = StringVar()

        # 嵌套函数:添加账户类型
        def add_main_accounts():
            if self.category_type.get() == "" or self.category_id.get() == "":
                tkinter.messagebox.showinfo('提示', '所有字段均为必填项')
            else:
                # 用已初始化的tb实例调用方法
                tb.insert_account_type(
                    self.category_type.get(),
                    self.category_id.get()
                )
                tkinter.messagebox.showinfo('成功', '条目添加完成')

        # 嵌套函数:显示账户类型(移除多余的self参数)
        def display_account_types():
            self.trv.delete(*self.trv.get_children())
            # 用tb实例调用查询方法
            for rows in tb.view_account_type():
                self.trv.insert("", END, values=rows)

        # 嵌套函数:获取选中行数据
        def get_account_type(e):
            self.selected_row = self.trv.focus()
            self.data = self.trv.item(self.selected_row)
            global row
            row = self.data["values"]
            # 修正索引:匹配数据库表结构(id, category_type, category_id)
            self.category_id.set(row[2])
            self.category_type.set(row[1])

        # TreeView配置
        ttk.Style().configure("Treeview", background="SlateGrey", foreground="white", fieldbackground="grey")

        scroll_x = Scrollbar(self.bot_frame, orient=HORIZONTAL)
        scroll_x.pack(side=BOTTOM, fill=X)

        scroll_y = Scrollbar(self.bot_frame, orient=VERTICAL)
        scroll_y.pack(side=RIGHT, fill=Y)

        self.trv = ttk.Treeview(self.bot_frame, height=3, columns=
        ('id', 'category_id', 'category_type'), xscrollcommand=scroll_x.set, yscrollcommand=scroll_y.set)

        ttk.Style().configure("Treeview", background="SlateGrey", foreground="white", fieldbackground="grey")

        scroll_x.config(command=self.trv.xview)
        scroll_y.config(command=self.trv.yview)

        # TreeView表头设置
        self.trv.heading('id', text="序号")
        self.trv.heading('category_id', text='分类ID')
        self.trv.heading('category_type', text='分类类型')

        self.trv['show'] = 'headings'

        # 列宽设置
        self.trv.column('id', width=23)
        self.trv.column('category_id', width=70)
        self.trv.column('category_type', width=100)

        self.trv.pack(fill=BOTH, expand=YES)

        # 绑定选中事件(修正转义字符)
        self.trv.bind('<ButtonRelease-1>', get_account_type)

        # 标签与输入框
        self.lbl1 = Label(self.right_frame, text='分类ID', anchor=W,
                          width=10, font=('cambria', 11), bg='SlateGrey')
        self.lbl1.grid(row=0, column=0, pady=5)

        self.lbl2 = Label(self.right_frame, text='分类类型', anchor=W,
                          width=10, font=('cambria', 11), bg='SlateGrey')
        self.lbl2.grid(row=1, column=0, pady=5, padx=5)

        self.blank_label = Label(self.right_frame, bg='SlateGrey')
        self.blank_label.grid(row=2, columnspan=2, pady=10)

        self.entry1 = Entry(self.right_frame, textvariable=self.category_id,
                            font=('cambria', 11), bg='Grey', width=14)
        self.entry1.grid(row=0, column=1, sticky=W, padx=5)

        self.entry2 = Entry(self.right_frame, textvariable=self.category_type,
                            font=('cambria', 11), bg='Grey', width=14)
        self.entry2.grid(row=1, column=1, sticky=W, pady=5, padx=5)

        # 功能按钮
        self.btn_1 = Button(self.right_frame, text='添加', font=('cambria', 12, 'bold'), bg='SlateGrey',
                            activebackground='green', fg='white', width=12, height=2, relief=RIDGE,
                            command=add_main_accounts)
        self.btn_1.grid(row=3, column=0, pady=15)

        self.btn_2 = Button(self.right_frame, text='查看', font=('cambria', 12, 'bold'),
                            bg='SlateGrey', command=display_account_types,
                            activebackground='green', fg='white', width=12, height=2, relief=RIDGE)
        self.btn_2.grid(row=3, column=1)

# 初始化Frontend实例
app = Frontend(root)

root.mainloop()

关键修改总结

  1. Backend类:
    • 移除__init__中SQL执行语句后的多余逗号
    • 修正insert_account_type的SQL参数,移除多余的self,并匹配字段顺序
  2. Frontend类:
    • 所有按钮command直接绑定函数,无需lambda包裹单个调用
    • 用tb实例调用Backend方法,替代直接用类调用
    • 移除嵌套函数display_account_types的self参数
    • 修正TreeView选中事件的转义字符,以及数据索引匹配数据库结构

内容的提问来源于stack exchange,提问作者B _J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 09:40:25