16

Python でいくつかの「基本」クラスを拡張しようとしています。

class xlist (list):
    def len(self):
        return len(self)

    def add(self, *args):
        self.extend(args)
        return None


class xint (int):
    def add(self, value):
        self += value
        return self


x = xlist([1,2,3])
print x.len()   ## >>> 3 ok
print x         ## >>> [1,2,3] ok
x.add (4, 5, 6)
print x         ## >>> [1,2,3,4,5,6] ok

x = xint(10)
print x         ## >>> 10 ok
x.add (2)
print x         ## >>> 10  # Not ok (#1)

print type(x)         ## >>> <class '__main__.xint'> ok
x += 5
print type(x)         ## >>> <type 'int'>  # Not ok (#2)

リストの場合、appendメソッドはオブジェクトを返すことなく「その場で」変更するため、うまく機能します。しかし、intの場合、addメソッドは外部x変数の値を変更しません。selfがクラスのaddメソッドのローカル変数であるという意味では問題ないと思いますが、これにより、クラスのインスタンスに割り当てられた初期値を変更できなくなります。

この方法でクラスを拡張することは可能ですか、それとも基本型でクラス プロパティを定義し、必要なすべてのメソッドをこのプロパティにマップする必要がありますか?

4

5 に答える 5

29

あなたの2つのxint例は、2つの異なる理由で機能しません。

最初のものは、ローカル変数を別のオブジェクト (整数) に再割り当てするだけで、元のオブジェクトを変更しないのself += valueと同等であるため、機能しません。あなたは本当にこれを得ることができませんself = self + valueself

>>> x = xint(10)
>>> x.add(2)

int整数はimmutableであるため、 のサブクラスを操作します。

2 番目のものを機能させるには、次のように__add__methodを定義できます。

class xint(int):
    def __add__(self, value):
        return xint(int.__add__(self, value))

>>> x = xint(10)
>>> type(x)
<class '__main__.xint'>
>>> x += 3
>>> x
13
>>> type(x)
<class '__main__.xint'>
于 2008-08-28T23:41:55.720 に答える
6

intは値型であるため、割り当てを行うたびに (たとえば、+=上記の両方のインスタンス)、ヒープ上にあるオブジェクトは変更されませんが、参照が右側の結果の 1 つに置き換えられます。代入 (すなわちint)

listは値型ではないため、同じ規則に拘束されません。

このページには、違いの詳細が記載されています: The Python Language Reference - 3. Data model

IMO、はい、int をインスタンス変数として保持する新しいクラスを定義する必要があります

于 2008-08-28T22:32:40.147 に答える
3

xlist クラスを少しだけ拡張して、数値のすべてのインデックス ポイントを見つけられるように作成したので、一度に複数のリストを拡張して初期化し、反復できるようになりました

class xlist:
    def __init__(self,alist):
        if type(alist)==type(' '):
            self.alist = [int(i) for i in alist.split(' ')]
        else:
            self.alist = alist
    def __iter__(self):
        i = 0
        while i<len(self.alist):
            yield self.alist[i]
            i+=1
    def len(self):
        return len(self.alist)
    def add(self, *args):
        if type(args[0])==type([1]):
            if len(args)>1:
                tmp = []
                [tmp.extend(i) for i in args]
                args = tmp
            else:args = args[0]
        if type(args)==type(''):args = [int(i) for i in args.split(' ')] 
        (self.alist).extend(args)
        return None
    def index(self,val):
        gen = (i for i,x in enumerate(self.alist) if x == val)
        return list(gen)
于 2011-07-24T20:30:07.467 に答える
0

int は不変であり、その場で変更することはできないため、オプション #2 を使用する必要があります (オプション #1 は、いくつかの策略がなければ不可能であるため)。

于 2008-08-28T22:28:36.413 に答える