希望能够通过传递关键字参数列表来为要使用的对象集合提供搜索界面,如下所示:
playerID = players.search(nameFirst='ichiro', nameLast='suzuki')
其中players.search的定义如下:
def search(self, **args):
ret = []
for playerID, player in self.iteritems():
for key, value in args.iteritems():
if getattr(player, key) == value:
ret.append(player.playerID)
return ret
显然上面的代码不起作用。我想借用一些SQL习语,像player.key == value和player.keyN = valueN一样工作,等等N个kwargs传递。
有什么想法吗?谢谢!
答案 0 :(得分:1)
您应该能够使用all
内置函数将其更改为列表推导,如果其参数中的所有元素都为true(或者如果iterable为空),则返回True。这样的事情可以解决问题:
for playerID, player in self.iteritems():
if all(getattr(player, key) == value for key, value in args.iteritems()):
ret.append(player.playerID)
答案 1 :(得分:1)
我想借用一些SQL习语, 像player.key == value一样工作 和player.keyN = valueN,依此类推 通过了N个kwargs。
所以你现在正在实现一个OR而想要实现一个AND而不是 - 是吗?
如果是这样的话,那么@ Mark的答案中建议的all
可以起作用 - 或者,等同地,尽管处于较低的抽象层次:
def search(self, **args):
ret = []
for playerID, player in self.iteritems():
for key, value in args.iteritems():
if getattr(player, key) != value: break
else:
ret.append(player.playerID)
return ret
我不太清楚为什么你在iteritems
上循环然后忽略你得到的密钥(直接附加player.playerID
而不是playerID
密钥)。
无论如何,另一种高抽象方法,假设你不需要密钥......:
def search(self, **args):
def vals(p):
return dict((k, getattr(p, k, None)) for k in args)
return [p.playerID for p in self.itervalues() if vals(p) == args]
这个不是“短路”,而是等同于马克的。完全等同,但非常简洁:
def search(self, **args):
return [p.playerID for p in self.itervalues()
if all(getattr(p, k, None)==args[k] for k in args)]
如果这些代码片段不能满足您的需求,并且您可以澄清它们为什么没有(理想情况下是一个或三个示例! - ),我确信它们可以进行调整以满足所述需求。