ユーザーが ipython のカスタム オブジェクトでタブ補完を使用するときに表示されるメソッドを制御したいと思います。特に、廃止された機能を非表示にしたいと考えています。これらのメソッドを呼び出し可能にしたいのですが、ユーザーがオブジェクトを検査している場合に、それらを見て使用を開始することは望ましくありません。これは可能なことですか?
4 に答える
あなたのための部分的な答え。サンプルコードを投稿し、なぜそれが部分的な答えにすぎないのかを説明します.
コード:
class hidden(object): # or whatever its parent class is
def __init__(self):
self.value = 4
def show(self):
return self.value
def change(self,n):
self.value = n
def __getattr__(self, attrname):
# put the dep'd method/attribute names here
deprecateds = ['dep_show','dep_change']
if attrname in deprecateds:
print("These aren't the methods you're looking for.")
def dep_change(n):
self.value = n
def dep_show():
return self.value
return eval(attrname)
else:
raise AttributeError, attrname
したがって、ここで注意が必要です。これらはメソッドではありません (最初の変数としての self がないことに注意してください)。ユーザー (またはコード) が非推奨のメソッドで im_class、im_func、または im_self を呼び出せるようにする必要がある場合、このハックは機能しません。また、内部で各依存関数を定義しているため、パフォーマンスが低下することは間違いありません__getattr__
。これは他の属性ルックアップには影響しませんが (それらを に入れて__getattribute__
いれば、別の問題になります)、これらの廃止されたメソッドへのアクセスが遅くなります。これは、リスト メンバーシップ チェックを行う代わりに、各関数定義を独自の if ブロック内に配置することで (大部分ではありますが完全ではありません) 無効にすることができますが、関数の大きさによっては、維持するのが非常に面倒になる可能性があります。
アップデート:
1)非推奨の関数メソッドを作成したい場合(そしてそうする場合)、単に使用します
import types
return types.MethodType(eval(attrname), self)
それ以外の
return eval(attrname)
上記のスニペットで、関数 defs の最初の引数として self を追加します。それらをインスタンスメソッドに変換します (つまり、im_class、im_func、および im_self を心ゆくまで使用できます)。
2)__getattr__
フックがあなたを興奮させなかった場合、別のオプションがあります(私が知っている)(ただし、独自の警告がありますが、それらに到達します):非推奨の関数定義を 内__init__
に置き、カスタムでそれらを非表示にします__dir__
. 上記のコードをこのように実行すると、次のようになります。
class hidden(object):
def __init__(self):
self.value = 4
from types import MethodType
def dep_show(self):
return self.value
self.__setattr__('dep_show', MethodType(dep_show, self))
def dep_change(self, n):
self.value = n
self.__setattr__('dep_change', MethodType(dep_change, self))
def show(self):
return self.value
def change(self, n):
self.value = n
def __dir__(self):
heritage = dir(super(self.__class__, self)) # inherited attributes
hide = ['dep_show', 'dep_change']
show = [k for k in self.__class__.__dict__.keys() + self.__dict__.keys() if not k in heritage + private]
return sorted(heritage + show)
ここでの利点は、ルックアップのたびに関数を新たに定義する必要がないため、速度が向上することです。ここでの欠点は、ルックアップごとに関数を新たに定義していないため、関数を「永続化」する必要があることです (必要に応じて)。そのため、カスタム__dir__
メソッドは廃止されたものを IPython のタブ補完から非表示にしますが、ユーザーがそれらを発見できるdir(hiddenObj)
インスタンスの属性にはまだ存在します。__dict__
dir(): によって呼び出されるイントロペクション用の特別な魔法のメソッド__dir__()
があるようです。それはあなたが探しているものではありませんか?
IPython の補完メカニズムについては、次のドキュメントに記載されています。
http://ipython.scipy.org/doc/manual/html/api/generated/IPython.core.completer.html#ipcompleter
しかし、あなたにとって本当に興味深い例は、あなたがやりたいことを正確に行う特性コンプリータです。これは、(名前に基づいて) いくつかのメソッドをオートコンプリートから隠します。
コードは次のとおりです。
DeprecationWarning
メソッドが呼び出されるまでは発行されないため、非推奨のメソッドの名前を格納するクラスに別の属性を設定し、補完を提案する前にそれを確認する必要があります。
あるいは、 を探してメソッドの AST をたどることもできますがDeprecationWarning
、クラスが C で定義されている場合、またはメソッドがDeprecationWarning
引数の型または値に基づいて を発行する可能性がある場合、これは失敗します。