5

あるとしましょう:

class A(B):
    ...

B可能性とobjectそう...ない場所:

@classmethod # or @staticmethod
def c(cls): print 'Hello from c!'

A.c()呼び出しがトリガーされないようにするにはどうすればよいAttributeErrorですか?

つまり、実行時に手動でクラス メソッドをクラスに追加できることを知っています。しかし、クラスメソッドが欠落するたびにダミーメソッドを作成するなど、自動的に行うことは可能ですか?

さらに別の言葉で言えば、A.__dict__処理する辞書に置き換えること__getitem__ができた場合にのみ、A.__dict__書き込み可能ではないようです...

4

3 に答える 3

14

これは、メタクラスで__getattr__フックを使用して実現できます。

class DefaultClassMethods(type):
    def __getattr__(cls, attr):
        def _defaultClassMethod(cls):
            print 'Hi, I am the default class method!'
        setattr(cls, attr, classmethod(_defaultClassMethod))
        return getattr(cls, attr)

デモ:

>>> class DefaultClassMethods(type):
...     def __getattr__(cls, attr):
...         def _defaultClassMethod(cls):
...             print 'Hi, I am the default class method!'
...         setattr(cls, attr, classmethod(_defaultClassMethod))
...         return getattr(cls, attr)
... 
>>> class A(object):
...     __metaclass__ = DefaultClassMethods
... 
>>> A.spam
<bound method DefaultClassMethods._defaultClassMethod of <class '__main__.A'>>
>>> A.spam()
Hi, I am the default class method!

classmethod呼び出しの結果をクラスに直接設定し、将来のルックアップのために効果的にキャッシュしていることに注意してください。

代わりに、すべての呼び出しでクラス メソッドを再生成する必要がある場合は、同じメソッドを使用して関数をインスタンスにバインドしますが、代わりにクラスとメタクラスを使用cls.__metaclass__します (メタクラスのサブクラス化と一貫性を保つために使用します)。

from types import MethodType

class DefaultClassMethods(type):
    def __getattr__(cls, attr):
        def _defaultClassMethod(cls):
            print 'Hi, I am the default class method!'
        return _defaultClassMethod.__get__(cls, cls.__metaclass__)

静的メソッドの場合、すべての場合に関数を直接返すだけで、staticmethodデコレータや記述子プロトコルをいじる必要はありません。

于 2012-07-01T11:56:03.590 に答える
1

や記述子プロトコルなどのメソッドによってインスタンスに提供される動作は__getattr__、クラスでも機能しますが、その場合、クラスのメタクラスでそれらをコーディングする必要があります。

__getattr__この場合、目的のクラス属性を自動生成するようにメタクラス関数を設定するだけです。

(setattr、getattr のトリックは、Python に関数 -> メソッド変換をいじる必要なく実行させることです)

class AutoClassMethod(type):
    def __getattr__(cls, attr):
        default = classmethod(lambda cls: "Default class method for " + repr(cls))
        setattr(cls, attr, default)
        return getattr(cls, attr)



class A(object):
    __metaclass__ = AutoClassMethod
    @classmethod
    def b(cls):
        print cls
于 2012-07-01T12:29:12.953 に答える
0
>>> class C(object):
...     pass
... 
>>> C.m = classmethod(lambda cls: cls.__name__)
>>> C.m()
'C'

または、次のようなものを使用できます。

class Wrapper(object):

    def __init__(self, clz, default=lambda cls: None):
        self._clz = clz
        self._default = default

    def __getattr__(self, attr):
        # __attrs__ will be getted from Wrapper
        if attr.startswith('__'):
            return self.__getattribute__(attr)

        if not hasattr(self._clz, attr):
            setattr(self._clz, attr, classmethod(self._default))
        return getattr(self._clz, attr)

    def __call__(self, *args, **kwargs):
        return self._clz(*args, **kwargs)

>>> class C(object):
...     pass
...
>>> C = Wrapper(C, default=lambda cls: cls.__name__)
>>> c = C()
>>> print C.m()
'C'
>>> print c.m() # now instance have method "m"
'C'
于 2012-07-01T12:03:45.080 に答える