2009-04-23 14 views
7

compact()と()はPHPの関数であり、非常に便利です。 compact()は、シンボルテーブル内の名前のリストを取り、その値だけでハッシュテーブルを作成します。抽出は逆です。例:PHPのcompact()とextract()のPython相当版

$foo = 'what'; 
$bar = 'ever'; 
$a = compact('foo', 'bar'); 
$a['foo'] 
# what 
$a['baz'] = 'another' 
extract(a) 
$baz 
# another 

Pythonで同じことを行う方法はありますか?私は周りを見てきました。私が一番近かったのはthis threadです。

私はlocals()、globals()、およびvars()について知っていますが、どうやってその値のサブセットを手軽に選択できますか?

Pythonにはこれを不要にするものがありますか?

+4

私は混乱していたことが分かりました。あなたの3行目は "$ a = compact( 'foo'、 'bar');"代わりに。 – pantsgolem

+0

おっと、ありがとうございます。私はちょうどそれを修正した。 – Turadg

+0

私はあなたがなぜそれを見つけるのが簡単なのか尋ねることはできますか?私は彼らがハッシュテーブルを使ってもっときちんと実装することができなかったものが良いのか分からない。 –

答えて

10

それは非常にPython的ではないですが、あなたが本当に必要がある場合:私は、これらの実装にかなりを使用しました

import inspect 

def compact(*names): 
    caller = inspect.stack()[1][0] # caller of compact() 
    vars = {} 
    for n in names: 
     if n in caller.f_locals: 
      vars[n] = caller.f_locals[n] 
     elif n in caller.f_globals: 
      vars[n] = caller.f_globals[n] 
    return vars 

def extract(vars): 
    caller = inspect.stack()[1][0] # caller of extract() 
    for n, v in vars.items(): 
     caller.f_locals[n] = v # NEVER DO THIS - not guaranteed to work 

、彼らは動作しますが、技術的にf_localsの変更はサポートされていません。

本当にあなたがこれらの機能を使用する必要があると感じたら、間違ったやり方をしている可能性があります。少なくとも3つのカウントでPython's philosophyに対して実行されているように見えます。「明示的な方が暗黙的に優れている」、「単純な方が複雑な方が良い」、「実装が説明が難しい場合は悪い考えです。あなたはPythonで十分な経験を持っていますが、このようなことは行われていないことを知っています)。私はそれがデバッガや死後の解析や、おそらく何らかの種類の非常に一般的なのフレームワークで、動的に選択された名前と値を持つ変数を作成する必要があるフレームワークにとっては便利だが、それはストレッチです。

これらの機能を使用する場合は、少なくともextract ed変数を小さなスコープ内に保持する必要があります。それらを「ブラックボックス」と考えることができる関数で囲みます。主な理由extractが悪いのは、コードを検査することから明らかではない方法でシンボルテーブルに変数を配置することです。これらの変数の効果を非常に小さな関数に限定して、明確なコードとコメントで何をしているのかを説明すれば、それほど大きな問題ではありません。

2

は、私はそれが私は、Pythonには同等物が存在しない怖いvars()

>>> foo, bar, baz = 1, 2, 3 
# extract 
>>> globals().update({"foo": 4, "qux": 5}) 
>>> foo 
4 
>>> qux 
5 
# compact 
>>> d = dict((k, v) for k, v in vars().iteritems() if k in ["foo", "bar"]) 
>>> d 
{'bar': 2, 'foo': 1} 
9

のサブセットですcompact()用としてextract($x)の同等は、globals().update(x)あると思います。ある程度までは、あなたが使用してその効果をシミュレートすることができます(とパッシング)locals:それでも

>>> def compact(locals, *keys): 
...  return dict((k, locals[k]) for k in keys) 
... 
>>> a = 10 
>>> b = 2 
>>> compact(locals(), 'a', 'b') 
{'a': 10, 'b': 2} 

>>> def extract(locals, d): 
...  for k, v in d.items(): 
...   locals[k] = v 
... 
>>> extract(locals(), {'a': 'foo', 'b': 'bar'} 
>>> a 
'foo' 
>>> b 
'bar' 

、私はこれらの関数は「途方もなく便利」とは思いません。動的なグローバル/ローカル変数は悪く、エラーを起こしやすい - PHPの人たちは、register_globalsを落としたときにそれを知った。私の経験から、経験豊富なPHPプログラマーや主要なフレームワークでは、compact()またはextract()を使用しています。 Pythonで

explicit is better than implicit

a = 1 
b = 2 
# compact 
c = dict(a=a, b=b) 

# extract 
a, b = d['a'], d['b'] 
+0

私はすべて明示的ですが、なぜそれは冗長でなければなりませんか? エラーが発生しにくいでしょうか? c = compact(a、b) – Turadg

+6

ローカル()を変更しないでください! http://docs.python.org/library/functions.html#locals –

6

extract()(およびより少ない程度に、compact())は(register_globalsevalと一緒に)PHPの最も「悪」の特徴の一つであり、避けるべきであることを指摘し、それは価値がありますか?

extractは、変数がどこで定義されたかを判断するのがずっと難しくなります。変数を定義された場所に戻すのが難しい場合は、初期化されていない変数やユーザー入力に由来するフィルタリングされていない変数のような一般的なセキュリティ上の問題を確認することは難しいでしょう。

compactはひどくはありませんが、ひどく使いすぎると、配列メンバが変数からどこにセットされているかを見るよりも難しくなります。

多くの言語でextract()に相当するのはwithです。 Pythonは今やwithというキーワードを持っていますが、少し違って動作しますが、extract()のようにはなりません。ただし、Javascriptなどの他の言語では、withキーワードalso has a poor reputationです。

私は、最良のアドバイスは、PHPの悪い機能をエミュレートしようとするのではなく、簡潔で読みやすいコードでやりたいことを他のやり方で考えようという考え方の違いだと思います。

+1

Pythonの 'with'ステートメントはJavaScriptとは全く異なるセマンティクスを持ち、「可変スコープ」は変更されません。また、それはかなり新しい機能であり、確かに評判が悪いことはありません。あなたはJavaScriptを使用しています。 –

+0

Ferdinandさん、ありがとうございました。私はちょっと答えを編集しました。 – thomasrutter

+0

1つのコメントには当てはまらないので意味がなくなりましたが、すべてが重要です。私はコメントに変換されたので、後でそれをロールバックしませんでした。あなたのコメントの最初の文章に書かれているように、何かを指摘しているだけなので、私はそれが質問に答えなかったと感じたので、私はそれを削除しました。 – Ryan

3

PythonでPHPのコンパクト機能(2.6で動作します。以前のバージョンのPythonでの動作が保証されていない):私はこれについて、より広範囲に書いた

import inspect 
def compact(*args): 
    return dict([(i, inspect.currentframe().f_back.f_locals.get(i, None)) 
        for i in args]) 

Python can be just as ugly as PHP

1

あなた更新可能dict返すlocals()機能、と(私は...難を示唆しているが)これを行うことができます。例:

$ python 
Python 2.7.12 (default, Jul 1 2016, 15:12:24) 
>>> locals().update({'derek':'anderson'}) 
>>> derek 
'anderson' 
>>> 

のでlocals()は "コンパクトすべて" だろうとlocals().update()extractだろう。

運が良かった!