3

我正在尝试使用 Python 中的流畅接口。

流畅的 sql 查询生成器的示例在使用中看起来像这样:

sql.select('foo').select('bar').from('sometable').tostring() 

我很快意识到递归定义嵌套类的能力可能会有所帮助。

class sql:
    class select:        
        class select   # <--  HERE
        def __init__(self, dbcolumn, astype=None, asname=None):
            self.dbcolumn = dbcolumn
            self.astype = astype
            self.asname = asname

在标有注释“# <-- HERE”的行中:
我希望这个嵌套类引用引用包含类的相同“选择”类定义。

这有可能吗?也许使用一些我不知道的关键字?

4

3 回答 3

7

不需要“递归类定义”。要允许链接,您需要做的就是self在您的方法中返回(或者如果您的对象不可变或某些方法不应修改输入对象,则返回同一类的实例)。

例子:

>>> class SQL(object):
...     def __init__(self):
...         self.columns = []
...     def select(self, col):
...         self.columns.append(col)
...         return self
...
>>> s = SQL()
>>> s.select('foo').select('bar').columns
['foo', 'bar']
于 2012-07-25T08:36:22.763 回答
0

正如问题的标题所示,我真的很想知道如何递归地嵌套类定义。我相信有很多方法可以“给 fluent-interface-in-python 猫换皮”。

我找到了一种使用装饰器递归嵌套类定义的方法:

# class decorator
def recursiveclass(decorated_class):
    decorated_class.__dict__[decorated_class.__name__] = decorated_class
    return decorated_class     

#fluent interface
class sql:
    @recursiveclass
    class select:        
        def __init__(self, dbcolumn, astype=None, asname=None):
            self.dbcolumn = dbcolumn
            self.astype = astype
            self.asname = asname

请注意,我并不是说这是在 Python 中实现流畅接口的最佳方式。我只是在做实验。

验证:

dir(sql.select.select.select.select)
['__doc__', '__init__', '__module__', 'select']
于 2012-07-25T09:07:36.570 回答
0

您将方法混淆了。

select是 的实例上的方法class sql,而不是嵌套类。它可以返回另一个实例。

class SelectStatement(object):
    def select(self, tablename):
        return SelectStatement()

class SQL(object):
    def select(self, tablename):
        return SelectStatement()

看一下SQLAlchemy的源代码;它正是这样做的;从结构 python 类生成 SQL,您可以通过以这种方式调用实例上的方法来优化查询。例如,可以链接一系列连接:

q = session.query(User).join(User.orders).join(Order.items).join(Item.keywords)
于 2012-07-25T08:36:24.010 回答