このメタクラスに基づくクラスで定義されたすべてのメソッドがデフォルトでクラスメソッド(つまり、@classmethod
の装飾などを必要とせず)であるようにメタクラスを書き込む方法はありますか?クラスメソッドをデフォルトにするメタクラス?
ありがとうございます!
編集:私はPython 2.7.3に興味があります。欠落をご容赦ください。
このメタクラスに基づくクラスで定義されたすべてのメソッドがデフォルトでクラスメソッド(つまり、@classmethod
の装飾などを必要とせず)であるようにメタクラスを書き込む方法はありますか?クラスメソッドをデフォルトにするメタクラス?
ありがとうございます!
編集:私はPython 2.7.3に興味があります。欠落をご容赦ください。
このような何か(2.7)
def m(name, bases, dct):
for k, v in dct.items():
if type(v) is type(m):
dct[k] = classmethod(v)
return type(name, bases, dct)
class A:
__metaclass__ = m
def foo(self):
print self
A.foo() # <class '__main__.A'>
確かに。本当の疑問はなぜあなたがこれをしたいと思うかです。私はこれが教育のためのものだと仮定しよう。実際には、これを使用できるものは明示的に行うほうがよいでしょう(つまり、メタクラスを使用せず、@classmethod
を追加する)。
私は2つのオプションを認識しています:クラス定義のカスタム名前空間と後処理は__new__
です。最初は非常に涼しく、場合によっては(例えばメソッド定義の順番を覚えている)避けられないものですが、後者はよりシンプルで柔軟性があり、複数の割り当てを誤って同じ名前に壊すことはありません。Python 2で利用できますあなたの目的は、これはかつての除外が、私はがカスタム名前空間を供給するためのPython 3
を使用することができます皆のためにそれを残しておきます、あなたはメタクラスで__prepare__
を定義し、辞書風を返す必要がオブジェクト(Ferdinand Beyerはコメントで注記:collections
で定義されているマッピングインターフェイスは十分です)。この場合、値がcallable
であるかどうかをチェックするには、辞書は__setitem__
を上書きする必要があります。その場合は、格納する前にclassmethod
にラップしてください。私は以下のコメントに多くの借りて、彼らは大幅に下のコードを改善した。 Ferdinand Beyerはcallable(classmethod(...))
が偽であり、agfは@classmethod
とPython 3の互換性に矛盾があることを指摘しました。
import types
# Either this, in a dictionary class instanciated in __prepare__
# Again, Python 3 only
def __setitem__(self, name, value):
if isinstance(value, types.FunctionType):
value = classmethod(value)
super().__setitem__(name, value)
# __prepare__ would be: return AutomaticClassMethodNamespace() or something
# Or this in the metaclass
def __new__(mcls, clsname, bases, ns):
for name, value in ns.items():
if isinstance(value, types.FunctionType):
ns[name] = classmethod(value)
# Any other metaclass behaviour
特に、 'callable'ではなく' types.FunctionType'を使うべきです。あなたはまた 'と'を意味します。メタクラスで '__new__'を使うと、同じ名前の複数の定義がどのように混乱するのかよく分かりません。なぜなら、各識別子がすでにひとつの値に解決されている辞書が得られるからです。 – agf
レコードの場合: '__prepare__'によって返されるオブジェクトは' dict'から継承する必要はなく、 ''マッピングインタフェースをサポートするだけです(例えば、 '' collections.MutableMapping'抽象基底クラスを使用する)。 http://docs.pythonを参照してください。org3/py3k/reference/datamodel.html#customizing-class-creation –
'classmethod'のインスタンスは呼び出し可能ではないので、余分なチェックは必要ありません。 –
関数をチェックする標準的な方法は、if isinstance(v、types.FunctionType): 'となります。これは 'm'、' k'、 'v'よりも意味のある名前を使用した方が良いでしょう。 – agf
@agf:私は呪文を信じていません。 – georg
私はそのコメントが何を意味すると思われるか分かりません。メタクラス関数の名前を変更するとします。コードが壊れます。関数の代わりに 'type'を継承するクラスを使用するように切り替えるとします。コードが壊れます。それが間接的に見つけるのではなく、あなたが意味する実際のタイプを使用する理由です。意味のある名前を使用すると、特に誰かに何かを説明するとき、基本的な常識です。 – agf