【问题标题】:Dataclasses - Basic method chaining数据类 - 基本方法链接
【发布时间】:2026-01-13 11:40:01
【问题描述】:

我正在尝试创建一个具有 2 个方法的类:

  • 查询数据(作为生成器)

  • 另存为 json

    @dataclass
    class Data_Query:
        hierarchic: str
        sku: bool
        pred_lenght: int
    
        def query(self, db):
           if (self.hierarchic == 'store' and self.sku == True):
               x = db.aggregate([{...}]);
               self.export_json(x) 
    
        def export_json(self, x, file):
            with open(f'/home/Documents/dataset/{file}', 'w') as fp:
                for i in x:
                    json.dump(i, fp)
                    fp.write('\n')
    

当我执行查询方法时,两个方法都会执行。

data = Data_Query('store', True, 56)
data.query(db)

我必须修改什么才能分开调用这些方法?

我的预期输出:

data.query(db).export_json('abc.json')

【问题讨论】:

  • 您的身份识别有误。而查询方法是由查询方法if (self.hierarchic == 'store' and self.sku == True): x = db.aggregate([{...}]); self.export_json(x) 这里执行的
  • 首先没有明显的理由让export_json 成为Data_Query 的方法。它需要的所有数据都作为两个显式参数传递。

标签: python python-dataclasses python-class


【解决方案1】:

不要直接从query 调用export_json,而是将结果保存在实例属性中并返回self 以启用链接。然后export_json 在实例上查找保存的查询,而不是将其作为参数。

@dataclass
class Data_Query:
    hierarchic: str
    sku: bool
    pred_lenght: int

    def query(self, db):
       if (self.hierarchic == 'store' and self.sku == True):
           self.x = db.aggregate([{...}]);
           # self.export_json(x) 
       return self

    def export_json(self, file):
        try:
            x = self.x
        except AttributeError:
            return
        
        with open(f'/home/Documents/dataset/{file}', 'w') as fp:
            for i in x:
                json.dump(i, fp)
                fp.write('\n')
        del self.x

现在你可以写data.query(db).export_json('abc.json'),和JSON文件 只有在实际上发生查询时才会写入。

但是,这并不是最棒的设计。 export_json 的任何内容都不是您的班级所特有的;它应该是一个接受结果和文件名的常规函数 并且您在进行查询之后调用 if 查询会返回任何结果。有点像

@dataclass
class Data_Query:
    hierarchic: str
    sku: bool
    pred_lenght: int

    def query(self, db):
       if (self.hierarchic == 'store' and self.sku == True):
           return db.aggregate([{...}])

def export_json(self, x, file):
    with open(f'/home/Documents/dataset/{file}', 'w') as fp:
        for i in x:
            json.dump(i, fp)
            fp.write('\n')

result = data.query(db)
if result is not None:
    export_json(result, 'abc.json')

可能争辩说“当然export_json 与我的类有关;它假定x 是对象的可迭代对象,这是由query 方法定义的。”在这种情况下,您可以考虑定义一个QueryResult 类,并使export_json 成为那个 类的方法。然后DataQuery.query 返回一个QueryResult 的实例,链接感觉不那么随意了:您导出的是result,而不是query

# By the way, I am assuming there is more to this class than a query
# method; otherwise, there should probably just be a regular function
# that takes the db, hierarchic, and sku as arguments.
@dataclass
class DataQuery:
    hierarchic: str
    sku: bool
    pred_length: int

    def query(self, db):
        result = None
        if self.hierarchic == 'store' and self.sku:
            result = db.aggregate(...)
        return QueryResult(result)


class QueryResult:
    def __init__(self, result):
        self.result = result

    def export_json(self, file):
        if self.result is None:
            return

        with open(f'/home/Documents/dataset/{file}', 'w') as fp:
           for i in x:
                json.dump(i, fp)
                fp.write('\n')


data.query(db).export_json('abc.json')

【讨论】:

  • 非常感谢@chepner,你真的帮助了我。你提出的最后一个建议正是我的情况。