-4

(「オブジェクト アドレス」とは、オブジェクトにアクセスするために Python で入力する文字列を意味します。たとえば、'life.State.step'.ほとんどの場合、最後のドットの前のすべてのオブジェクトはパッケージ/モジュールになりますが、場合によってはクラスまたは他のオブジェクトになります。)

私のPython プロジェクトでは、オブジェクト アドレスをいじる必要がよくあります。私がしなければならないいくつかのタスク:

  1. オブジェクトを指定して、そのアドレスを取得します。
  2. アドレスを指定してオブジェクトを取得し、途中で必要なモジュールをインポートします。
  3. 冗長な中間モジュールを取り除くことにより、オブジェクトのアドレスを短縮します。(たとえば'life.life.State.step'、オブジェクトの正式なアドレスかもしれませんが'life.State.step'、同じオブジェクトを指している場合は、より短いので代わりに使用したいと思います。)
  4. 指定されたモジュールを「ルート化」することにより、オブジェクトのアドレスを短縮します。(たとえば'garlicsim_lib.simpacks.prisoner.prisoner.State.step'、オブジェクトの正式な住所かもしれませんが、ユーザーはパッケージがどこにあるかを知っていると想定しているprisonerので、住所として使用したいと思い'prisoner.prisoner.State.step'ます。)

そのようなことを処理するモジュール/フレームワークはありますか? これらのことを行うためにいくつかのユーティリティ モジュールを作成しましたが、これを行うより成熟したモジュールを誰かが既に作成している場合は、それを使用したいと思います。

1 つの注意: これらの簡単な実装を見せようとしないでください。見た目よりも複雑で、多くの落とし穴があり、簡単なコードは多くの重要なケースで失敗する可能性があります。この種のタスクには、実戦でテスト済みのコードが必要です。

更新:「オブジェクト」と言うときは、ほとんどの場合、クラス、モジュール、関数、メソッドなどを意味します。前にこれを明確にしなかったことをお詫び申し上げます。

4

4 に答える 4

5

短い答え: いいえ。あなたが望むことは不可能です。

長い答えは、オブジェクトの「アドレス」と考えるものは何でもないということです。特定の時点でlife.State.stepオブジェクトへの参照を取得する方法の 1 つにすぎません。後で同じ「アドレス」を使用しても、別のオブジェクトが返されるか、エラーになる可能性があります。さらに、あなたのこの「住所」は文脈によって異なります。では、エンド オブジェクトはとが何であるかだけでなく、その名前が名前空間で参照するオブジェクトにも依存します。life.State.steplife.Statelife.State.steplife

リクエストに対する具体的な回答:

  1. 最終オブジェクトには、それをどのように参照したかを知る方法はまったくありません。また、オブジェクトに与えるコードもありません。「アドレス」は名前ではなく、オブジェクトに関連付けられていません。これは、オブジェクト参照になる任意のPython式にすぎません (すべての式がそうであるように)。クラスやモジュールなど、動き回ることが予想されます。それでも、それらのオブジェクト動き回る可能性があり、頻繁に動き回るため、試みたものは壊れる可能性があります。

  2. 前述のように、「アドレス」は多くのことに依存しますが、この部分はかなり簡単です。これらのもの__import__()getattr()提供できます。ただし、属性へのアクセスだけでなく、より複雑な場合は特に、非常に脆弱です。モジュール内のもののみをリモートで操作できます。

  3. 名前を「短縮」するには、考えられるすべての name、つまりすべてのモジュールとすべてのローカル名、およびそれらのすべての属性を再帰的に調べる必要があります。__getattr__これは非常に遅く、時間のかかるプロセスであり、メソッドや__getattribute__メソッド、または値を返す以上のことを行うプロパティに直面すると、非常に壊れやすくなります。

  4. 3と同じです。

于 2010-09-10T11:37:50.743 に答える
4

address_tools私が求めていたことを正確に実行するモジュールをリリースしました。

ここにコードがありますここにテストがあります

GarlicSimの一部なので、インストールgarlicsimして実行するだけで使用できますfrom garlicsim.general_misc import address_tools。その主な機能はdescribeおよびresolveであり、 および と同等reprですeval。docstring は、これらの関数がどのように機能するかについてすべて説明しています。

GarlicSimの Python 3 フォークには Python 3 バージョンもあります。address_toolsPython 3 コードで使用する場合は、インストールしてください。

于 2010-12-23T22:52:24.527 に答える
1

ポイント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ます)。

ただし、このようにコーディングすることは非常に珍しいことです。

于 2010-09-10T11:34:06.463 に答える
0

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

ここで、'handler' が実際には前の式 return から _ に入っていて、これが最短の名前になっていることがわかります。

すべてのモジュールのすべてのメンバーを再帰的に検索するなど、他の何かが必要な場合は、コードを作成してください。しかし、「_」の例が示すように、驚きがあります。さらに、別のモジュールをインポートすると、別のオブジェクト パスが使用可能になり、短くなる可能性があるため、これは安定していません。

そういうわけで、あなたが欲しいものは実際には何の役にも立たないと人々が何度も繰り返し言い、それがモジュールがない理由です。

4 番目については、一般的なパッケージでこれらのネーミングのニーズにどのように対応できますか?

いずれにせよ、あなたは書いた

これらの簡単な実装を私に見せようとしないでください。見た目よりも複雑で、多くの落とし穴があり、簡単なコードは多くの重要なケースで失敗する可能性があります。この種のタスクには、実戦でテスト済みのコードが必要です。

したがって、私の例を解決策と考えないでください。あなたが求めていることがほとんど意味をなさない理由の例として考えてください。それは非常に壊れやすいソリューション空間であり、(主に好奇心のために) そこに足を踏み入れる少数の人々は非常に異なる懸念を持っているため、1 回限りのカスタム ソリューションが最適です。これらのほとんどのモジュールは意味がありません。意味がある場合、モジュールが何をするかの説明はおそらくコードよりも長くなります。

したがって、あなたの質問に対する答えは「いいえ、そのようなモジュールはありません」です。

あなたの質問をさらに混乱させるのは、PythonのC実装がすでに「オブジェクトアドレス」を定義していることです。id()のドキュメントは次のように述べています。

CPython 実装の詳細: これはオブジェクトのアドレスです。

探しているのは、オブジェクトの名前またはパスです。「Python オブジェクト アドレス」ではありません。

于 2011-01-27T20:05:58.463 に答える