Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.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_List Comprehension - Fatal编程技术网

Python 基于选择的列表理解

Python 基于选择的列表理解,python,list-comprehension,Python,List Comprehension,基本上,如果我要编写一个具有可变返回元素的函数,如下所示: 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

基本上,如果我要编写一个具有可变返回元素的函数,如下所示:

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]]

但是如果用户不需要,我不想计算元素;计算其中的一些操作有点昂贵。

如果在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]

问一个稍微不同的问题,你能得到像matlab/octave这样的行为吗?在matlab/octave中,如果你分配给两个变量,你只计算前两个结果,而不计算结果3和4

例如:

a, b = func()
Python不能完全做到这一点,因为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)
我不确定它是否更好,但您可以使用decorator添加数组索引语义,这将允许您编写:

@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()[:]
给出:

== compute all four
compute 1
compute 2
compute 3
compute 4
== compute first two
compute 1
compute 2
== compute one only
compute 1
== all as a list
compute 1
compute 2
compute 3
compute 4