Python 2 では、任意の callable をクラスのメソッドに変換することができました。重要なのは、callable が C で実装された CPython 組み込みである場合、これを使用して、それ自体が C レイヤーであるユーザー定義クラスのメソッドを作成し、呼び出されたときにバイト コードを呼び出さないことです。
これは、「ロックのない」同期を提供するために GIL に依存している場合に役立つことがあります。GIL は op コード間でしか交換できないため、コードの特定の部分のすべてのステップを C にプッシュできる場合は、アトミックに動作させることができます。
Python 2 では、次のようなことができます。
import types
from operator import attrgetter
class Foo(object):
... This class maintains a member named length storing the length...
def __len__(self):
return self.length # We don't want this, because we're trying to push all work to C
# Instead, we explicitly make an unbound method that uses attrgetter to achieve
# the same result as above __len__, but without no byte code invoked to satisfy it
Foo.__len__ = types.MethodType(attrgetter('length'), None, Foo)
Python 3 では、バインドされていないメソッド型はなくなり、types.MethodType
2 つの引数のみを取り、バインドされたメソッドのみを作成します (これは__len__
、__hash__
、 などの Python の特殊なメソッドには役に立ちません。特殊なメソッドは、多くの場合、型で直接検索されるため、インスタンスではありません)。
私が見逃しているPy3でこれを達成する方法はありますか?
私が見たもの:
functools.partialmethod
(C実装がないように見えるため、要件に失敗し、Python実装と必要以上に汎用的であるため、遅く、テストで約5 usかかりますが、直接の場合は約200〜300 nsかかりますPython 定義またはattrgetter
Py2 では、オーバーヘッドが約 20 倍増加します)attrgetter
非データ記述子プロトコルに従おうとするなど(AFAICTでは不可能、a__get__
などでモンキーパッチを適用できない)attrgetter
を与えるためにサブクラス化する方法を見つけようとしています__get__
が、もちろん、__get__
何らかの方法で C レイヤーに委譲する必要があり、今では最初の場所に戻っています。attrgetter
(ユースケースに固有)__slots__
最初にメンバーを記述子にするために使用し、その後、データの結果の記述子から、実際の値をバインドして取得する最終ステップをスキップして、呼び出し可能にする何かに変換しようとしますしたがって、実際の値の取得は延期されます
ただし、これらのオプションのいずれについても、何かを見逃していないとは言えません。誰にも解決策はありますか?完全なハッキングが許可されています。私はここで病的なことをしていることを認識しています。柔軟であることが理想的です ( 、 、 などclass
の Python 組み込み関数、または Python レイヤーで定義されていないその他の呼び出し可能なオブジェクトから、バインドされていないメソッドのように動作するものを作成できるようにするため)。重要なことに、各インスタンスではなく、クラスにアタッチする必要があります (インスタンスごとのオーバーヘッドを削減し、ほとんどの場合インスタンス ルックアップをバイパスする特別なメソッドを正しく動作させるため)。hex
len