Python中的递归类定义
我正在用Python测试流畅的接口 fluent sql查询生成器的一个示例在使用中类似于以下内容:Python中的递归类定义,python,class,recursion,fluent-interface,python-2.x,Python,Class,Recursion,Fluent Interface,Python 2.x,我正在用Python测试流畅的接口 fluent sql查询生成器的一个示例在使用中类似于以下内容: sql.select('foo').select('bar').from('sometable').tostring() 我很快意识到递归定义嵌套类的能力可能会有所帮助 class sql: class select: class select # <-- HERE def __init__(self, dbcolumn,
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
在标有注释“的行中,不需要递归类定义。如果对象是不可变的,或者某些方法不应该修改输入对象,那么允许链接只需在方法或同一类的实例中返回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']
你把类和方法混淆了
select是类sql实例上的方法,而不是嵌套类。它可以返回另一个实例
class SelectStatement(object):
def select(self, tablename):
return SelectStatement()
class SQL(object):
def select(self, tablename):
return SelectStatement()
看看的源代码;它确实做到了这一点;从python类的结构生成SQL,您可以通过以这种方式调用实例上的方法来优化查询。例如,可以链接一系列连接:
q = session.query(User).join(User.orders).join(Order.items).join(Item.keywords)
正如问题的标题所示,我真的很想知道如何递归嵌套类定义。我相信有很多方法可以“在python cat中为流畅的界面换肤” 我找到了一种使用decorator递归嵌套类定义的方法:
# 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']
但是select是sql上的一种方法;它可以返回一个类,但它本身不是一个类..这是。。。不是如何实现fluent接口。可以公平地说,fluent接口不是Python中的工作方式吗?@chrismorge:no,只是没有嵌套类定义来实现fluent接口。@MartijnPieters:select不是一个方法,只是一个嵌套类。调用sql.select'foo'显然调用了sql.select类的构造函数,返回了嵌套的select类的一个实例?这个例子的问题是,添加一个SQL.insert函数将使这样的事情成为可能:s.select'foo'。insert在SQL fluent接口中没有意义。只需在调用select时设置一个标志,并在对设置了select标志的对象调用insert时引发一个异常。这听起来像是一个不必要的攻击。如果python更好的代码完成兼容性建议的标志也不会起到很好的作用。但这只是一个理论上的缺陷,这里没有混淆。也许我用小写的类名把你弄糊涂了@Ries:不,我很确定我没有被弄糊涂。无论如何,谢谢你链接到SQLAlchemy。@Ries:你想基于另一个实例的上下文返回类实例吗。你可以通过各种方法做到这一点;如果你只是实例化了一个嵌套类,它将不会继承该上下文。有关如何传递上下文的方法,请参阅。但我同意,它使用了一个实例化同一类的方法。但我仍然喜欢嵌套的类结构。上面的例子确实展示了如何递归嵌套类,但我开始怀疑这样做的有用性,因为子类无法访问其父类的属性。也许这对于定义流畅的接口更有意义: