2011-12-21 10 views
0

リスト内でリスト内のリストに作用する関数をどのように構築するのが難しいですか? 、基本的には、最初の値は常に文字列となりますPythonでリスト内のリストから関数を構築する

getattr(getattr(getattr(getattr(res, x[0]), x[1][0]), x[1][1][0]), x[1][1][1]) 

getattr(getattr(getattr(getattr(res, 'neighborhood'), 'city'), 'metro'), 'metro') 

AKA:

は私が動的に

res = SomeDjangoQuerySet 
x = ['neighborhood', ['city', ['metro', 'metro']]] 

のようなリストをオンにしようとしています2番目の値は文字列またはリストのいずれかになります。各リストはこのパターン(文字列、文字列ORリスト)に従います。リスト内のリストの深さは不確定です。 getattr()の最も内側の最初の値は外部変数(この場合は 'res')になります。何かアドバイス?

答えて

3

これは再帰と同じように聞こえ、繰り返しが便利です。これはあなたが望むことをしますか?

def flatten(data): 
    res = [] 
    if hasattr(data, '__iter__'): 
     for el in data: 
      res.extend(flatten(el)) 
    else: 
     res.append(data) 
    return res 


reduce(getattr, flatten(x), res) 
+0

ここでの再帰は間違いなく重要です。これはうまくいきますが、私はそれに従うのが少し難しいと感じました。私は別の方法を思いついてしまいました。(しかし、あなたの返信には全く同じことがありました!) – alukach

+0

もう一度撮影した後、これは間違いありません。ここで学んだクールなものがあります(hasattr()とreduce())。ありがとう。 – alukach

1
def nestattr(x, y): 
    if isinstance(y, str): 
     return getattr(x, y) 
    elif isinstance(y, list): 
     return nestattr(getattr(x, y[0]), y[1]) 

nestattr(res, x) 

だから、リスト内の最初の文字列から始め、そしてあなたは、(2)その文字列で(1)クエリのgetattrを持っています。その後、そのリストの残りの部分を使用して再帰します。文字列の場合は、getattrには、前のgetattrの結果に(2)この文字列を(1)だけ入力します。それ以外の場合は、まだリストの場合は、繰り返します。私はこれがあなたが探しているものだと思いますか?私が間違っているなら私を訂正してください。

+0

私はこのバージョンが壊れていると思います。リストの終わりに達すると、空のリストが関数に渡され、 'y [0]'の例外がスローされます。 –

+0

これは私にとってはうまくいかず、最後にy [0]に当たると 'TypeError:getattr():属性名は文字列でなければなりません。 – alukach

+0

おっと、y [1:]にコロンが必要ないと思います。スライスを取る必要はありませんでした。あなたの解決策を見つけたようですが、とにかく修正を行います。 –

1

私はいくつかの時間を入れて再帰について学習し、これが最も簡単な解決策であることを発見しました(ただし、David Zwickerにも実用的なソリューションを提供しました)。

def recursion(a, b): 
    if type(b) is list: 
     return recursion(getattr(a, b[0]), b[1]) 
    else: 
     return getattr(a, b) 

recursion(res, x) 
+0

あなたのバージョンは、リストにちょうど2つの要素がある場合にのみ機能します。これが常に当てはまると分かっているならば、それは当然正当ですが、注意することが重要です!また、別のリストの最初の位置にネストされたリストがある場合、メソッドは完全には機能しません。 –

関連する問題