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

Python实现SQL查询包装函数报错:'function' object has no attribute 'cursor'

问题分析与修复

错误根源

你的装饰器写法犯了两个核心错误:

  1. 装饰器参数传递错误:sql_select是类的实例方法,需要接收self参数,但用@sql_select装饰test时,Python会把test函数当作第一个参数传给sql_select,导致sql_select里的self变成了test函数对象,后续访问self.cursor自然会报错'function' object has no attribute 'cursor'。
  2. 未正确调用被装饰方法:你直接把func(即test函数对象)塞进了SQL模板,没有执行它来获取实际的SQL语句,而且test作为实例方法需要接收self参数才能正常执行。

修复后的代码

import sqlite3
import threading

class DatabaseManagment():

    def __init__(self) -> None:
        self.con = sqlite3.connect("test.db")
        self.cursor = self.con.cursor()
        self.lock = threading.Lock()

    # 改成静态方法的装饰器,避免实例绑定问题
    @staticmethod
    def sql_select(func):
        def inner(self):
            # 调用被装饰的实例方法,传入self获取SQL语句
            sql = func(self)
            # 加锁保证线程安全
            with self.lock:
                self.cursor.execute(sql)
                return self.cursor.fetchall()
        return inner

    @sql_select
    def test(self):
        return "SELECT * FROM App_price"

关键改动说明

  • 将sql_select改为静态方法:这样在类定义阶段装饰test时,不会涉及实例的self绑定问题,能正确接收被装饰的函数func。
  • 让inner函数接收self参数:作为实例方法的包装,inner需要访问实例的cursor和lock,同时通过func(self)调用被装饰的方法,获取返回的SQL语句。
  • 加入线程锁:利用你初始化的lock,通过with语句自动管理锁的获取和释放,避免多线程环境下的数据库操作冲突。

扩展优化(可选)

如果需要支持带参数的SQL查询(比如SELECT * FROM App_price WHERE id = ?),可以修改装饰器和被装饰方法,传入参数:

@staticmethod
def sql_select(func):
    def inner(self, *args, **kwargs):
        sql = func(self, *args, **kwargs)
        with self.lock:
            self.cursor.execute(sql, args)
            return self.cursor.fetchall()
    return inner

@sql_select
def get_price_by_id(self, price_id):
    return "SELECT * FROM App_price WHERE id = ?"

这样调用db.get_price_by_id(1)时,参数会被自动传递给SQL的占位符,更灵活实用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 11:46:02