13

を呼び出すクラスがあるとしましょう__new__。mro をうまく操作し、__new__必要に応じて (引数を使用して) スーパー クラスを呼び出しobject.__new__、追加の引数を使用しないようにするにはどうすればよいでしょうか? たとえば、これはコンストラクターに引数を渡さない場合にのみ機能します。

class A(object):
    def __new__(cls, *args, **kwargs):
        print("A.__new__ called")
        return super(A, cls).__new__(cls, *args, **kwargs)

class B(object):
    def __new__(cls, *args, **kwargs):
        print("B.__new__ called")
        return super(B, cls).__new__(cls, *args, **kwargs)

class C(A, B): pass

>>> C.mro()
[__main__.C, __main__.A, __main__.B, builtins.object]
>>> C()
A.__new__ called
B.__new__ called

ただし、引数を指定して呼び出すと失敗します (ある時点で、Python がobject.__new__呼び出し元クラス以外のパラメーターを受け入れないように変更されたため)。

>>> C(1)
A.__new__ called
B.__new__ called
Traceback (most recent call last):
   ...
TypeError: object() takes no parameters

ではAB彼らのスーパークラスがobject. 私は何かをする必要がありますsuper(A, cls).__new__ is object.__new__か?それを確認しmro()[1] == builtins.objectますか?それとも、「A​​ はスーパー クラスを適切に呼び出そうとしない__new__」と判断する必要がありますか(たとえば、実行することによってreturn object.__new__(cls))?

編集: クラスがカスタム メソッドを定義する場合__init__、Python 2.6 と Python 2.7 はそれで問題ありませんが、Python 3 ではまだ動作しません。

4

2 に答える 2

2

__new__それ自体が使用し、必要とした引数を渡さないのは、実際にはカスタムメソッド次第です。どちらもCBまたは引数を必要としない場合、例外が発生するAという事実は完全に正しいです。object.__new__()

カスタムもあるすぐに、例外も発生しないことに注意してください。これは、残りの引数次の場所に渡す場所があるためです。__init__ object.__new__

>>> class A(object):
...     def __new__(cls, *args, **kwargs):
...         print("A.__new__ called")
...         return super(A, cls).__new__(cls, *args, **kwargs)
... 
>>> class B(object):
...     def __new__(cls, *args, **kwargs):
...         print("B.__new__ called")
...         return super(B, cls).__new__(cls, *args, **kwargs)
... 
>>> class C(A, B):
...     def __init__(self, *args, **kwargs):
...         print args, kwargs
... 
>>> C(1)
A.__new__ called
B.__new__ called
(1,) {}
<__main__.C object at 0x10e7f9790>

この動作は Python 3 で変更されたようです。

どのメソッドが返されるかをテストできます。__new__

class B(object):
    def __new__(cls, *args, **kwargs):
        new = super(B, cls).__new__
        if new is object.__new__:
            return new(cls)
        return new(cls, *args, **kwargs)
于 2013-10-31T23:08:48.673 に答える