43

Python 2.2 の変更ログ (新しいスタイルのクラスが導入された場所) は、__new__関数について次のように述べています。

__new__クラスメソッドではなく静的メソッドです。最初はクラス メソッドでなければならないと思っていたので、classmethodプリミティブを追加しました。残念ながら、クラス メソッドでは、この場合アップコールが正しく機能しないため、最初の引数として明示的なクラスを持つ静的メソッドにする必要がありました。

しかし、なぜクラス メソッドがこの目的で機能しないのか、私には思いつきません。__new__最終的にクラスメソッドにならなかったのはなぜですか? Guido が「この場合、upcall が正しく機能しない」と言うとき、何を参照していますか?

4

1 に答える 1

29

__new__静的メソッドであるため、サブクラスのインスタンスを作成するときにユースケースが可能になります。

return super(<currentclass>, cls).__new__(subcls, *args, **kwargs)

newがクラス メソッドの場合、上記は次のように記述されます。

return super(<currentclass>, cls).new(*args, **kwargs)

置く場所がありませんsubcls

ただし、それがいつ適切な使用になるかはわかりません__new__。多分私はそれを見ていないかもしれませんが、それは完全に病理学的な使用のように思えます(そして、それでも本当にそれが必要な場合は、 でアクセスできますobject.__new__.__func__)。少なくとも、それが Guido__new__のクラス メソッドから静的メソッドへの変更の理由だったとは想像しがたいと思います。

より一般的なケースは、__new__を使用せずに親を呼び出すことsuper()です。この場合、明示的に渡す場所が必要ですcls:

class Base(object):
    @classmethod
    def new(cls):
        print("Base.new(%r)" % (cls,))
        return cls()

class UseSuper(Base):
    @classmethod
    def new(cls):
        print("UseSuper.new(%r)" % (cls,))
        return super(UseSuper, cls).new() # passes cls as the first arg

class NoSuper(Base):
    @classmethod
    def new(cls):
        print("NoSuper.new(%r)" % (cls,))
        return Base.new()  # passes Base as the first arg

class UseFunc(Base):
    @classmethod
    def new(cls):
        print("UseFunc.new(%r)" % (cls,))
        return Base.new.im_func(cls)  # or `.__func__(cls)`. # passes cls as the first arg

print(UseSuper.new())
print('-'*60)
print(NoSuper.new())
print('-'*60)
print(UseFunc.new())
于 2012-02-01T08:22:27.390 に答える