Python の構文を言語内から直接変更する方法はありません。辞書内包表記 (または単純な表示) は常に を作成しますがdict
、それに対してできることは何もありません。CPython を使用している場合は、dict を直接生成する特別なバイトコードを使用しており、最終的にPyDict
API 関数やその API で使用される同じ基になる関数を呼び出します。PyPy を使用している場合、これらのバイトコードは代わりdict
に、コンパイルおよび最適化された Python の上に実装される RPython オブジェクトの上に実装されdict
ます。等々。
間接的な方法もありますが、気に入らないでしょう。import systemのドキュメントを読むと、キャッシュされたコンパイル済みコードを検索したり、コンパイラを呼び出したりするのはインポーターであり、パーサーを呼び出すのはコンパイラなどであることがわかります。Python 3.3+ では、このチェーンのほとんどすべてが純粋な Python で記述されているか、代替の純粋な Python 実装を備えているため、コードをフォークして独自のことを行うことができます。これには、AST を構築する独自の PyParsing コードを使用してソースを解析する、辞書内包表記 AST ノードをデフォルトではなく独自のカスタム バイトコードにコンパイルする、バイトコードを後処理する、または…</p>
多くの場合、インポート フックで十分です。そうでない場合は、いつでもカスタム ファインダーとローダーを作成できます。
まだ Python 3.3 以降を使用していない場合は、これを試す前に移行することを強くお勧めします。古いバージョンでは、それはより難しく、十分に文書化されておらず、移行するたびに時代遅れになるものを学ぶために、最終的には 10 倍の労力を費やすことになります。
とにかく、このアプローチが興味深いと思われる場合は、MacroPyを見てください。そこからいくつかのコードを借りることができます。そして、おそらくもっと重要なこととして、これらの機能 (ドキュメントには良い例がありません) のいくつかがどのように使用されているかを学ぶことができます。
または、あまりクールではないもので解決したい場合は、 を使用MacroPy
して「odict 内包マクロ」を作成し、それを使用することができます。(現在、MacroPy は Python 2.7 でのみ動作し、3.x では動作しないことに注意してください。) 完全に を取得することはできませんo{…}
が、たとえば を取得することはできますod[{…}]
。これはそれほど悪くはありません。od.py
、realmain.py
、および をダウンロードmain.py
して実行python main.py
し、動作することを確認します。キーはこのコードで、AST を受け取り、それをkey-value s でDictionaryComp
同等のものに変換し、 toでラップします。GeneratorExpr
Tuple
Call
collections.OrderedDict
def od(tree, **kw):
pair = ast.Tuple(elts=[tree.key, tree.value])
gx = ast.GeneratorExp(elt=pair, generators=tree.generators)
odict = ast.Attribute(value=ast.Name(id='collections'),
attr='OrderedDict')
call = ast.Call(func=odict, args=[gx], keywords=[])
return call
もちろん、別の方法として、Python インタープリターを変更します。
最初はO{…}
構文のアイデアを捨てて、通常の dict 内包表記を odict にコンパイルすることをお勧めします。幸いなことに、文法を変更する必要は実際にはありません (毛むくじゃらではありません…)。
- dictcomps がコンパイルするバイトコード、
- インタープリターがそれらのバイトコードを実行する方法、または
PyDict
型の実装
悪いニュースは、これらはすべて文法を変更するよりもはるかに簡単ですが、拡張モジュールから実行できるものはありません。(ええと、基本的に純粋な Python から行うのと同じことを行うことで最初のものを行うことができます….so/.dll/.dylib をフックして独自の関数にパッチを適用することで、それらのいずれかを行うことができますが、それはPython でのハッキングとまったく同じ作業に加えて、実行時にフックする追加の作業が必要です。)
CPython のソースをハックしたい場合、必要なコードはPython/compile.c
、Python/ceval.c
、およびObjects/dictobject.c
にあります。開発ガイドには、必要なものすべてを見つける方法が記載されています。しかし、 PyPy ソースは C ではなく Python (のサブセット) でほとんど書かれているため、代わりにPyPy ソースのハッキングを検討することをお勧めします。
補足として、すべてが Python 言語レベルで行われたとしても、あなたの試みはうまくいきませんでした。モジュールのグローバルで名前がolddict, dict = dict, OrderedDict
付けられたバインディングを作成します。これは組み込みの名前を隠しますが、置き換えません。ビルトイン内のものを置き換えることができます(まあ、Pythonはこれを保証しませんが、私が試したすべての実装/バージョンで機能する実装/バージョン固有のものがあります…)が、あなたがしたことはそれを行う方法ではありません。dict