5

Python バージョン: "'2.7.3 (デフォルト、2013 年 4 月 10 日、06:20:15) \n[GCC 4.6.3]'"

私はこれを持っています:

>>> class testclass1(object):
    ...     pass
    ... 

>>> class testclass2(object):
    ...     def __init__(self,param):
    ...             pass
    ... 

>>> a = object.__new__(testclass1, 56)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: object.__new__() takes no parameters

>>> b = object.__new__(testclass2, 56)

>>> b
    <__main__.testclass2 object at 0x276a5d0>

もっと楽しい!上記の testclass1 の結果と比較してください。

>>> class testclass3(object):
    ...     def __init__(self):
    ...             pass
    ... 

>>> c = object.__new__(testclass3, 56)

>>> c
    <__main__.testclass3 object at 0x276a790>

>>> c1 = object.__new__(testclass3)

>>> c1
    <__main__.testclass3 object at 0x276a810>

私の質問は、これら 2 つのケースで(理由ではなく)どのように異なる動作をするかです。object__new__また、最初のケースではエラーが誤解を招く可能性があることに注意してください。2 番目のケースでobject.__new__は引数を取ることになるからです。

4

3 に答える 3

6

どちらもobject.__new__object.__init__場合によっては過剰な引数を許可し、他の場合にはエラーを発生させ、非常に具体的なものでは警告を発生させる、慎重に構築された条件の迷路を通過します。チェックを実装するコードは簡単に理解できますが、その背後にある理由は、この説明的なコメントがなければ不可解なままになる可能性があります。

がオーバーライドされていないobject.__new__()ときだけ引数について文句を言うのはなぜでしょうか。object.__init__()

使用例を検討してください。

  1. どちらもオーバーライドされていない場合、過剰な (つまり、任意の) 引数についての苦情を聞きたいと思います。それらの存在はバグがあることを示している可能性があるためです。

  2. 不変型を定義するときは、不変オブジェクトを初期化するには が呼び出されるのが遅すぎる__new__()ため、のみをオーバーライドする可能性があります。__init__()は型のシグネチャを定義しているため、余分な引数について不平を言うのを止めるためだけに__new__()オーバーライドしなければならないのは面倒です。__init__()

  3. Mutable 型を定義するときは、 のみをオーバーライドする可能性があります__init__()__new__()したがって、ここでは逆の理由が適用されます。不平を言うのを止めるためだけにオーバーライドする必要はありません。

  4. __init__()オーバーライドされ、サブクラス__init__()が を呼び出すobject.__init__()場合、後者は過剰な引数について文句を言う必要があります。についても同様です__new__()

ユースケース 2 と 3 では、余分な引数を無条件にチェックするのは魅力的ではありません。4 つのユース ケースすべてに対応する最適な__init__()ソリューション __new__()は次のとおり__init__()です 。対称的に、オーバーライドされている場合とオーバーライドされていない場合 (IOW、オーバーライドされているかオーバーライド されていない場合)を除いて、過剰な引数について文句を言い ます。__init__()__new__()__new__()__init__()__new__()__new__()__init__()

ただし、後方互換性のために、これは多くのコードを壊します。したがって、2.6 では、両方のメソッドがオーバーライドされたときに過剰な引数について警告します。他のすべてのケースでは、上記のルールを使用します。

于 2013-09-08T14:44:58.630 に答える
3

作成しているクラス__init__()には、作成パラメーターを処理するために呼び出されるメンバーがありnew()ますが、最初のケースでは、パラメーターがない__init__ため、パラメーターを渡すことができません。

于 2013-09-08T06:03:51.293 に答える
3

static メソッドは、最初の__new__引数としてクラスを受け取ります。__init__他の引数は、そのクラスのメソッドに渡されます。クラスには__init__メソッド__new__がないため、他の引数を受け入れません。

詳細については、ドキュメントを参照してください。

「方法」に関しては、C ( Objects/typeobject.c) で実装されていますが、純粋な Python で同じチェックを実行できます。

def __new__(cls, *args, **kwargs):
    ...

    if not hasattr(cls, '__init__') and (args or kwargs):
        raise TypeError("object.__init__() takes no parameters")

    ...
于 2013-09-08T06:04:01.870 に答える