我在真正的Django函数中得到了这段代码。如果符合某些条件,则会将项目添加到list
。
ret = []
if self.taken():
ret.append('taken')
if self.suggested():
ret.append('suggested')
#.... many more conditions and appends...
return ret
非常功能。你知道它做了什么,那很好......
但我学会了欣赏list
和dict
理解的美丽。
是否有更多的 Pythonic 方法来表达这个结构,也许是一次性初始化并填充数组?
答案 0 :(得分:3)
创建一个映射字典:
self.map_dict = {'taken': self.taken,
'suggested': self.suggested,
'foo' : self.bar}
[x for x in ['taken', 'suggested', 'foo'] if self.map_dict.get(x, lambda:False)()]
相关:Most efficient way of making an if-elif-elif-else statement when the else is done the most?
答案 1 :(得分:2)
没有太大的改进,但我会提到它:
def populate():
if self.taken():
yield 'taken'
if self.suggested():
yield 'suggested'
ret = list(populate())
我们可以做得更好吗?我持怀疑态度。显然,需要使用另一种语法而不是列表文字,因为我们不再有“结果中的1表达式= 1元素”不变。
编辑:
我们的数据有一个模式,它是(条件,值)对的列表。我们可能会尝试使用它来利用它:
[value
for condition, value
in [(self.taken(), 'taken'),
(self.suggested(), 'suggested')]
if condition]
但是这仍然是对你如何描述你的逻辑的一个限制,无论条件如何(除非你投入大量的lambda),仍然有评估所有值的令人讨厌的副作用,我不能真正看到它比我们开始时的改进。
答案 2 :(得分:1)
对于这个非常具体的示例,我可以这样做:
return [x for x in ['taken', 'suggested', ...] if getattr(self, x)()]
但同样,这个仅在它调用的项目和方法检查时具有相同的名称,即我的确切代码。它可以调整,但它有点硬皮。我对其他解决方案非常开放!
答案 3 :(得分:1)
我不知道为什么我们要附加与函数名称匹配的字符串,但如果这是一般模式,我们可以使用它。函数具有__name__
属性,我认为它总是包含您在列表中的内容。
那怎么样:
return [fn.__name__ for fn in (self.taken, self.suggested, foo, bar, baz) if fn()]
如果我正确理解了这个问题,那么非成员函数和成员函数一样。
编辑:
好的,我们添加一个映射字典。并将函数名称拆分为元组或列表。
fns_to_check = (self.taken, self.suggested, foo, bar, baz)
# This holds only the exceptions; if a function isn't in here,
# we will use the .__name__ attribute.
fn_name_map = {foo:'alternate', bar:'other'}
def fn_name(fn):
"""Return name from exceptions map, or .__name__ if not in map"""
return fn_name_map.get(fn, fn.__name__)
return [fn_name(fn) for fn in fns_to_check if fn()]
您也可以使用@ hcwhsa的映射字典答案。这里的主要区别是我建议只映射异常。
答案 4 :(得分:0)
在另一个实例中(其中一个值将被定义但可能是None - 在我的情况下是一个Django模型的字段),我发现只需添加它们并过滤工作:
return filter(None, [self.user, self.partner])
如果其中任何一个是None
,它们将从列表中删除。它比仅仅检查更加密集,但是在不写书的情况下仍然可以非常简单地清理输出。
答案 5 :(得分:0)
一个选择是拥有一个“哨兵”风格的对象来代替失败相应条件的列表条目。然后可以定义一个函数,以filter删除丢失的项目:
# "sentinel indicating a list element that should be skipped
Skip = object()
def drop_missing(itr):
"""returns an iterator yielding all but Skip objects from the given itr"""
return filter(lambda v: v is not Skip, itr)
借助这种简单的机制,我们可以相当接近列表理解样式的语法:
return drop_skips([
'taken' if self.taken else Skip,
'suggested' if self.suggested else Skip,
100 if self.full else Skip,
// many other values and conditions
])