基本上,如果我要编写一个带有可变返回元素的函数,就像这样:
def func(elem1=True, elem2=True, elem3=True, elem4=False):
x = MyClass()
ret = []
if elem1:
ret.extend([x.func1()])
if elem2:
ret.extend([x.obj1])
if elem3:
ret.extend([x.func2().attr1])
if elem4:
ret.extend(x.list_obj3)
return ret
事情变得漫长而多风。是否有可能做这样的事情:
def func(elem1=True, elem2=True, elem3=True, elem4=False):
x = MyClass()
return [x.func1() if elem1,
x.obj1 if elem2,
x.func2().attr1 if elem3,
x.list_obj3 if elem4]
多么整洁!?
我知道可以做到这一点:
def func(elem1=True, elem2=True, elem3=True, elem4=False):
x = MyClass()
ret = [x.func1(), x.obj1, x.func2().attr1, x.list_obj3]
choices = [elem1, elem2, elem3, elem4]
return [r for i, r in enumerate(ret) if choices[i]]
但是如果用户不想要它们,我想不计算它们;计算其中一些是有点贵。
答案 0 :(得分:5)
如果你在lambdas中隐藏你的操作,那么你可以使用延迟评估:
def func(elem1=True, elem2=True, elem3=True, elem4=False):
x = MyClass()
return [L() for inc,L in (
(elem1, lambda: x.func1()),
(elem2, lambda: x.obj1),
(elem3, lambda: x.func2().attr1),
(elem4, lambda: x.list_obj3),
) if inc]
答案 1 :(得分:1)
问一个稍微不同的问题,你能得到像matlab / octave这样的行为,你只计算前两个结果,如果你分配两个变量,而没有计算结果3和4?
例如:
let entity:NSManagedObject = data?.object(at: i) as! NSManagedObject
if let expensesAmount = entity.value(forKey: "expensesAmount") as? NSNumber {
totalAmount += expensesAmount.floatValue
}
由于func()并不知道它想要多少返回值,所以Python无法做到这一点,但你可以使用它来接近:
a, b = func()
我不确定它是否更好,但您可以使用装饰器添加数组索引语义,这将允许您编写:
from itertools import islice
def func():
x = MyClass()
yield x.fun c1()
yield x.obj1
yield x.func2().attr1
yield x.list_obj3
a, b = islice(func(), 2)
这很容易实现:
@sliceable
def func():
...
a, b = func()[:2]
测试:
from itertools import islice
class SlicedIterator(object):
def __init__(self, it):
self.it = it
def __iter__(self):
return self.it
def __getitem__(self, idx):
if not isinstance(idx, slice):
for _ in range(idx): next(self.it)
return next(self.it)
return list(islice(self.it, idx.start, idx.stop, idx.step))
def sliceable(f):
def wraps(*args, **kw):
return SlicedIterator(f(*args, **kw))
return wraps
给出:
@sliceable
def f():
print("compute 1")
yield 1
print("compute 2")
yield 2
print("compute 3")
yield 3
print("compute 4")
yield 4
print("== compute all four")
a, b, c, d = f()
print("== compute first two")
a, b = f()[:2]
print("== compute one only")
a = f()[0]
print("== all as a list")
a = f()[:]