Pythonメタプログラミングノート

1つの言語でのプログラミング経験の蓄積により、私たちは皆、自分用の標準的なプログラミング手法を開発しています。 私たちの経験が高ければ高いほど、その数は多くなり、彼らの仕事の方法はより多様になります。 別の言語に切り替えるとき、それらを再現しようとします。 時には、それらのいくつかが無関係または効果的でないことが起こります。 ほとんどの場合、私たちにとって珍しい新しい方法は言語学習から奪われます。 Pythonの機能のうち、最初はわからなかった機能をいくつか指摘したいと思います。

概して、Pythonでは、すべてのオブジェクトは辞書に保存されます辞書-辞書全体に固有のキーを持つオブジェクトのリストがあります。

class A(): i=1; s='string'
print dir(A)

> ['__doc__', '__module__', 'i', 's']


このプロパティを使用すると、クラスやクラスインスタンスでさまざまなことを「取得」できます。 例:

class A(): v0=1
class B(A):
v1=2
def __init__(self):
self.v2 = 3

b=B()
print b.v2, b.v1, b.v0

> 3 2 1


Pythonがv2を取得しようとしたとき、すべてが明確です-インスタンスbの辞書から取得されます。 さらに興味深いことに、プロパティv1には要素bが含まれておらず、辞書Bが含まれています-Pythonがそこから取得しました。 そして最後に、要素v0を検索するとき、親BAのディクショナリを検索し、そこから取り出します。 プロパティv0がb内で決定される場合、その値はより高いレベルに上昇することなくそこから取得されることは明らかです。

def __init__(self):
print self

class A(): pass
setattr(A, '__init__', __init__)

a=A()

> <__main__.A instance at 0x009E9EB8>



この例では、__ init__関数をクラスAの制限に移動しました(他の名前で関数を移動できます。説明のために__init__を提供しています)。 クラス宣言は次と同等です:

class A():
def __init__(self):
print self



Pythonのクラスは、メタクラスのインスタンスです。 これは驚きです。なぜなら、インスタンスだけでなく、その場でクラスを定義できるようになったからです。

def __init__(self):
print self

B = type('B', (), {})
setattr(B, '__init__', __init__)

b = B()


> <__ main __。0x009E7CD0のBオブジェクト>



関数はクラスのインスタンスに対してのみ定義され、クラスA自体に対しては呼び出せないことに注意してください。 一方、この機会を追加することを妨げているのは何ですか。

def Omd(obj):
print obj

B = type('B', (), {})
setattr(B, 'c', classmethod(Omd))
setattr(B, 'o', Omd)

b = B()
bc(), bo()


> <クラス '__main __。B'>
> <__ main __。0x009E7D50のBオブジェクト>

本当に楽しいですか?! 最初の引数を出力する関数を特定しました。 次に、メタクラスに基づいてクラスを作成しました( class A(type): passとして標準的に定義できます)。 クラスの隣に、私たちのものが隠されている静的関数「c」と、クラスBのインスタンスからそれを呼び出す関数「o」を追加しました。最初にクラスが表示され、その後にインスタンスが表示されます。 これが彼らの愛です。

Source: https://habr.com/ru/post/J64359/


All Articles