2016-11-17 21 views
2

基本的な選択に基づいて:リスト内包、

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

が、私は、ユーザーがそれらを望んでいない場合の要素を計算していないしたいと思います。それらのいくつかを計算するのは少し高価です。

答えて

5

あなたがラムダであなたの業務を非表示にした場合、あなたは、遅延評価を使用することができますわずかに異なる質問をする

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

を、あなたは、MATLAB /オクターブのような動作を得ることができ、あなたの場合は、最初の2つの結果を計算するところ結果3と4を計算せずに2つの変数に代入していますか?

例えば

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) 

私はそれが良いのか分かりませんが、配列インデクシングのセマンティクスをデコレータを使って追加すると、次のように書くことができます:

@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