4

namedtuple からサブクラス化されたクラスを定義する方法を理解していないと思います:

from collections import namedtuple
PD = namedtuple('PD', 'x y z')
p1 = PD(0, 'u', 1)
print p1.x #<== this works

class PDsub(PD):
   __slots__ = ()
   def __new__(cls, x, y, z):
        self = super(PDsub, cls).__new__(cls, x, y, z)
        return self

   def __init__(self, a):
        self.x, self.y, self.z = a, a, a

   def __str__(self):
        return 'Foo'

p2 = PDsub(5) #<== this does not work

このコードはTypeError : __new__() takes exactly 4 arguments (2 given).

理由はありますか?

4

2 に答える 2

6

インスタンス コンストラクター ( __new__) とインスタンス初期化子 ( __init__) の両方が同じ数の引数を受け入れる必要があります。

__new__4 つの引数が必要ですが、メソッドは 2 つしか受け入れませ__init__ん。どちらか一方を調整して同じ数を受け入れるか、メソッド*argsでキャッチオール引数を使用します__init__

たとえば、次の__new__メソッドを使用すると、機能します。

def __new__(cls, a):
    self = super(PDsub, cls).__new__(cls, a, a, a)
    return self

その場合、__init__イニシャライザはまったく必要ありません。

デモ:

>>> from collections import namedtuple
>>> PD = namedtuple('PD', 'x y z')
>>> class PDsub(PD):
...     __slots__ = ()
...     def __new__(cls, a):
...         self = super(PDsub, cls).__new__(cls, a, a, a)
...         return self
...     def __str__(self):
...         return 'Foo'
... 
>>> p2 = PDsub(5)
>>> p2.x, p2.y, p2.z
(5, 5, 5)
>>> str(p2)
'Foo'

タプルのような不変型は、多くの場合、初期化子の代わり__new__にコンストラクターを使用します。すべての組み込みの不変 ( 、、) がそうします。__init__frozensetstrtuple

于 2012-10-05T11:55:16.817 に答える
2
def __new__(cls, x, y, z):

p2 = PDsub(5)

クラスのオブジェクトを作成するたびに、__new__メソッド (コンストラクター) が呼び出されて作成されます。したがって、ここでは__new__メソッドに 4 つのパラメーターが必要ですが、2 つしか渡していません (*注: - パラメーターclsは暗黙的です) 。

したがって、2 つのパラメーター__new__を受け取るように変更するか、 4 つのパラメーターを受け取るように変更し、それに応じて3 つのパラメーターを渡して作成することができます(最初のパラメーターは暗黙的です..)__init__your instance

于 2012-10-05T11:58:00.307 に答える