Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的递归类定义_Python_Class_Recursion_Fluent Interface_Python 2.x - Fatal编程技术网

Python中的递归类定义

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,

我正在用Python测试流畅的接口

fluent 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

在标有注释“的行中,不需要递归类定义。如果对象是不可变的,或者某些方法不应该修改输入对象,那么允许链接只需在方法或同一类的实例中返回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:你想基于另一个实例的上下文返回类实例吗。你可以通过各种方法做到这一点;如果你只是实例化了一个嵌套类,它将不会继承该上下文。有关如何传递上下文的方法,请参阅。但我同意,它使用了一个实例化同一类的方法。但我仍然喜欢嵌套的类结构。上面的例子确实展示了如何递归嵌套类,但我开始怀疑这样做的有用性,因为子类无法访问其父类的属性。也许这对于定义流畅的接口更有意义: