我想调用这样的函数:
select().orderBy()
首先调用select()
,然后调用orderBy()
。
为了实现它,我将一个方法定义为select方法,如下所示:
def select(self):
if self.key is not None:
self.request = """SELECT """ + self.key[0] + """ FROM """ + self.table
else:
self.request = """SELECT * FROM """ + self.table
def where():
self.request += """ WHERE """ + self.key[0] + """ = """ + self.value[0]
return self.request
def orderBy(key, value):
self.request += """ ORDER BY """ + key + """ """ + value
return self.request
def groupBy(arg):
self.request += """ GROUP BY """ + arg
return self.request
def limit(arg):
self.request += """ LIMIT """ + arg
return self.request
但是我有这样的错误信息:
AttributeError: 'NoneType' object has no attribute 'orderBy'
有人知道该怎么做吗?
答案 0 :(得分:5)
链接方法(流畅的或生成的API)仅在前面的调用返回支持下一个方法的对象时才有效;在foo().bar()
中,foo()
必须返回具有.bar()
方法的对象。您的.select()
方法返回None
,这是一个不支持任何其他方法的对象。
您的select
函数应返回self
:
return self
呼叫是可链接的。您可能希望其他调用也返回self
,而不是self.request
。我在这里假设其他方法确实是同一个类的方法(你的例子是每个方法缺少self
个参数)。
如果您尝试仅将这些方法用于select()
方法中,那么这些方法可用,那么 。这些函数对象只是函数体中未使用的本地名称,它们在返回的对象上不可用。
如果这些方法不应存在于定义select
的同一个类中,请定义 new 类并让该类实现额外的方法。让select()
返回该类的实例:
class Selectable:
# ...
def select(self):
column = '*' if new_clone.key is None else new_clone.key
request = """SELECT {} FROM {}""".format(column, new_clone.table)
return Query(request)
class Query:
def __init__(self, request):
self.request = request
def where(self):
self.request += """ WHERE """ + self.key[0] + """ = """ + self.value[0]
return self
def orderBy(self, key, value):
self.request += """ ORDER BY """ + key + """ """ + value
return self
def groupBy(self, arg):
self.request += """ GROUP BY """ + arg
return self
def limit(self, arg):
self.request += """ LIMIT """ + arg
return self
请注意,Query()
上的每个方法都会返回self
,因此您可以继续链接。
但是,您正在操作同一个实例,并且无法从公共库创建单独的查询对象。 SQLAlchemy做得更好;它返回self
的克隆,并添加了更改:
def _clone(self):
return type(self)(self.request)
def where(self):
new_clone = self._clone()
new_clone.request += """ WHERE {} = {}""".format(self.key[0], self.value[0])
return new_clone
现在base = Selectable().select()
和filtered = base.where()
使filtered
成为一个独特的克隆,因此您可以继续使用base
来构建其他查询。
(实际上,SQLAlchemy使用decorator替换self
和newly created clone。