Pythonオブジェクトアドレスを処理するためのPythonモジュールはありますか?
-
02-10-2019 - |
質問
(「オブジェクトアドレス」と言うとき、私はあなたがPythonに入力する文字列を意味してオブジェクトにアクセスします。たとえば 'life.State.step'
. 。ほとんどの場合、最後のドットの前のすべてのオブジェクトはパッケージ/モジュールになりますが、場合によってはクラスまたは他のオブジェクトにすることができます。)
私の中で Pythonプロジェクト 私はしばしばオブジェクトアドレスをいじくり回す必要があります。私がしなければならないいくつかのタスク:
- オブジェクトが与えられた場合、アドレスを取得します。
- アドレスを指定して、オブジェクトを取得し、必要なモジュールを途中でインポートします。
- 冗長な中間モジュールを取り除くことにより、オブジェクトのアドレスを短縮します。 (例えば、
'life.life.State.step'
オブジェクトの公式アドレスかもしれませんが、'life.State.step'
同じオブジェクトをポイントします。代わりに、それが短いので使用したいと思います。) - 指定されたモジュールを「根付かせる」ことにより、オブジェクトのアドレスを短縮します。 (例えば、
'garlicsim_lib.simpacks.prisoner.prisoner.State.step'
オブジェクトの公式アドレスである可能性がありますが、ユーザーがどこにあるかを知っていると思いますprisoner
パッケージは、使用したいと思います'prisoner.prisoner.State.step'
住所として。)
そのようなものを処理するモジュール/フレームワークはありますか?私はこれらのことをするためにいくつかのユーティリティモジュールを書きましたが、誰かがこれを行うより成熟したモジュールをすでに書いているなら、私はそれを使用したいと思います。
1つの注:これらのことの迅速な実装を私に見せようとしないでください。それは見た目よりも複雑です、多くのゴッチャがあり、多くの重要なケースではおそらく迅速なn-dirtyコードが失敗するでしょう。これらの種類のタスクには、戦闘テストされたコードが必要です。
アップデート: 「オブジェクト」と言うとき、私は主にクラス、モジュール、関数、メソッド、このようなものを意味します。これを明確にしてくれなかったのは申し訳ありません。
解決 2
私はリリースしました address_tools
私が求めたことを正確に行うモジュール。
それはの一部です garlicsim, 、したがって、あなたはそれを使用することができます インストール garlicsim
そしてやっている from garlicsim.general_misc import address_tools
. 。その主な機能はです describe
と resolve
, 、それに平行です repr
と eval
. 。 Docstringsは、これらの機能がどのように機能するかについてのすべてを説明しています。
Python 3バージョンもあります ガリシムのPython 3フォーク. 。使用する場合はインストールしてください address_tools
Python 3コード。
他のヒント
簡単な答え:いいえ。あなたが望むものは不可能です。
長い答えは、あなたがオブジェクトの「アドレス」と考えているものは何でもないということです。 life.State.step
オブジェクトへの参照を取得する方法の1つにすぎません その特定の時点で. 。後の時点で同じ「アドレス」が別のオブジェクトを与えることも、エラーになる可能性があります。さらに、あなたのこの「アドレス」 コンテキストに依存します. 。の life.State.step
, 、エンドオブジェクトは、何に依存しません life.State
と life.State.step
あるが、 名前はどのようなものですか life
その名前空間で言及します.
リクエストに対する具体的な回答:
エンドオブジェクトにはあります まったくありません あなたがそれをどのように参照したかを知ることの中で、またあなたがオブジェクトを与えるコードも持っていません。 「アドレス」は名前ではなく、オブジェクトに結び付けられていません。オブジェクトの参照をもたらす任意のPython式です(すべての式がそうであるように)。 かろうじて, 、クラスやモジュールなど、動き回るとは期待されていない特定のオブジェクトを使用します。それでも、それらのオブジェクト できる 動き回って頻繁に移動します 行う 動き回るので、あなたが試みることは壊れる可能性が高い。
前述のように、「アドレス」は多くのことに依存しますが、この部分はかなり簡単です。
__import__()
とgetattr()
これらのものを与えることができます。ただし、特に属性アクセスよりも多くの場合、非常に脆弱です。モジュールにあるものでのみリモートで動作することができます。「短縮」名前では調べる必要があります すべての可能な名前, 、すべてのモジュールとすべてのローカル名を意味し、 それらのすべての属性, 、募集的に。それは非常に遅く、時間のかかるプロセスであり、何かに直面して非常に脆弱です
__getattr__
また__getattribute__
メソッド、または値を返す以上のことを行うプロパティを使用します。3と同じです。
ポイント3と4の場合、私はあなたが次のような施設を探していると思います
from life import life # life represents life.life
from garlicsim_lib.simpacks import prisoner
ただし、これは推奨されません。あなたやあなたのコードを読んでいる人が迅速に何を知るかを難しくするため、これは推奨されません。 prisoner
表す(モジュールはどこから来るのか?この情報を取得するためにコードの先頭を見る必要がある)。
ポイント1については、次のことができます。
from uncertainties import UFloat
print UFloat.__module__ # prints 'uncertainties'
import sys
module_of_UFloat = sys.modules[UFloat.__module__]
ポイント2の場合、文字列「garlicsim_lib.simpacks.prisoner」を考えると、次のようなオブジェクトを取得できます。
obj = eval('garlicsim_lib.simpacks.prisoner')
これにより、モジュールをインポートしたことがあります
import garlicsim_lib # or garlicsim_lib.simpacks
これを自動にしたい場合は、のラインに沿って何かをすることができます
import imp
module_name = address_string.split('.', 1)[0]
mod_info = imp.find_module(module_name)
try:
imp.load_module(module_name, *mod_info)
finally:
# Proper closing of the module file:
if mod_info[0] is not None:
mod_info[0].close()
これは、最も単純な場合にのみ機能します(garlicsim_lib.simpacks
で利用できる必要があります garlicsim_lib
, 、 例えば)。
ただし、この方法でコーディングするのは非常に珍しいことです。
Twistedは、Twisted/Python/Reflect.pyとして#2を持っています。 djangoのurls.py構成のように、文字列ベースの構成システムを作成するには、そのようなものが必要です。
コードとバージョン制御ログを見て、それを機能させるために何をしなければならなかったかを確認し、失敗します! - 正しい方法。
あなたが探している他のものは、汎用解決策のようなものがないため、Python環境に十分な制限があります。
これがあなたの#1をいくらか実装するものです
>>> import pickle
>>> def identify(f):
... name = f.__name__
... module_name = pickle.whichmodule(f, name)
... return module_name + "." + name
...
>>> identify(math.cos)
'math.cos'
>>> from xml.sax.saxutils import handler
>>> identify(handler)
'__main__.xml.sax.handler'
>>>
#3は未定義です。私が行った場合
__builtin__.step = path.to.your.stap
次に、検索コードはそれを「ステップ」として見つける必要がありますか?
最も単純な実装では、すべてのモジュールを単純に検索し、まさにあなたが望むものであるトップレベルの要素を探すことができます
>>> import sys
>>> def _find_paths(x):
... for module_name, module in sys.modules.items():
... if module is None:
... continue
... for (member_name, obj) in module.__dict__.items():
... if obj is x:
... yield module_name + "." + member_name
...
>>> def find_shortest_name_to_object(x):
... return min( (len(name), name) for name in _find_paths(x) )[1]
...
>>> find_shortest_name_to_object(handler)
'__builtin__._'
>>> 5
5
>>> find_shortest_name_to_object(handler)
'xml.sax.handler'
>>>
ここでは、「ハンドラー」が実際に_以前の式の復帰から_であり、最短の名前になっていることがわかります。
すべてのモジュールのすべてのメンバーを再帰的に検索するなど、他の何かが必要な場合は、コードアップするだけです。しかし、「_」の例が示すように、驚きがあります。さらに、別のモジュールをインポートすると別のオブジェクトパスが利用可能になり、短くなる可能性があるため、これは安定していません。
だからこそ、人々はあなたが望むものは実際には何にも役に立たないと何度も何度も言っています。だから、それはモジュールがない理由です。
そして、あなたの#4に関しては、世界の一般的なパッケージはどのようにしてそれらの命名のニーズに応えるでしょうか?
いずれにせよ、あなたは書いた
これらのことの迅速な実装を私に見せようとしないでください。それは見た目よりも複雑です、多くのゴッチャがあり、多くの重要なケースではおそらく迅速なn-dirtyコードが失敗するでしょう。これらの種類のタスクには、戦闘テストされたコードが必要です。
ですから、私の例を解決策として考えないでください。それは非常に壊れやすいソリューションスペースです(主に好奇心のために)そこに冒険する少数の人は、1回限りのカスタムソリューションが最良のものであるように異なる懸念を持っています。これらのほとんどのモジュールは意味がありません。もしそれが理にかなっていれば、モジュールが何をするかについての説明がおそらくコードよりも長くなるでしょう。
したがって、あなたの質問に対する答えは「いいえ、そのようなモジュールはありません」です。
あなたの質問をさらに混乱させるのは、PythonのC実装がすでに「オブジェクトアドレス」を定義していることです。 id()のdocs いう:
cpython実装の詳細:これはオブジェクトのアドレスです。
あなたが探しているのは、名前、またはオブジェクトへの道です。 「Pythonオブジェクトアドレス」ではありません。