1

次のコードはNoneを返しませんが、いくつかの不思議な「メイン_.link_listオブジェクト」を返します。

class link_list(object):
    """a link list class"""
    def __init__(self, list):
        super(link_list, self).__init__()
        pdb.set_trace()
        if list==[]:
            return None
        else:
            self.value = list[0]
            self.next = link_list(list[1:len(list)])

テストコードは「False」を出力します。

l=link_list([1,2,3])
print l.next.next.next==None

なんで?

4

2 に答える 2

6

.__init__()実際にはコンストラクターではありません。

コンストラクターとしての__init__?

Noneから戻るかどうかに関係なく、オブジェクトが作成されます.__init__()。コメントで@IgnacioVazquez-Abramsが指摘しているように、Pythonは;からの戻り値として期待しています。 とにかく他に何も返すことはできません。ある種の壊滅的なエラーを通知する必要がある場合は、例外を発生させる必要があります。None.__init__()

あなたの例では、おそらく、「ヘッド」参照と「テール」参照を持つ完全なリンクリストを表すクラスと、リンクリストのデータエントリを表す別のクラスが必要です。次に、リンクリストクラス自体をチェックしてnullリストをテストできますhead is None

編集:もう少し考えてみると、シングルクラスの実装が機能します。内部に設定.nextする必要があるだけです。これがあなたのコードの私の編集です:None.__init__()

class link_list(object):
    """a link list class"""
    def __init__(self, lst):
        super(link_list, self).__init__()
        pdb.set_trace()
        if len(lst) > 1:
            self.value = lst[0]
            self.next = link_list(lst[1:])
            print "id == %d, linked in %d" % (id(self), id(self.next))
        elif len(lst) == 1:
            self.value = lst[0]
            self.next = None
            print "length-one case: id == %d" % id(self)
        else:
            self.value = None
            self.next = None
            print "length-zero case: id == %d" % id(self)

l=link_list([1,2,3])
print l.next.next.next is None

ノート:

  • インデントを修正しました。

  • 組み込み型をシャドウイングしないように、変数名のlst代わりに使用しました。listlist

  • 何が起こっているかを監視するのに役立ついくつかの印刷ステートメントを追加しました。

編集:そして、完全を期すために、2つのクラスを使用した実装を示します。リストを表し、長さがゼロの可能性があるクラスと、リスト内の1つのエントリを表すクラスです。ループはエントリのforチェーンを構築し、任意のシーケンス(イテレータを含む)からリストを構築できます。スライスは使用されないため、シーケンスはリストである必要はありません。

class link_list_val(object):
    """one value for a linked list"""
    def __init__(self, value):
        self.value = value
        self.next = None

class link_list(object):
    """a link list class"""
    def __init__(self, seq):
        self.head = None

        for value in seq:
            x = link_list_val(value)
            if self.head is None:
                self.head = x;
                cur = x
            else:
                cur.next = x
                cur = x

l=link_list([1,2,3])
print l.head.next.next.next is None

編集:これがもう1つのバージョンです。これは、末尾再帰ではなく、反復を使用してリンクリストを作成しますが、単一のクラスで作成します。秘訣は、.__init__()関数がリンクリスト全体を構築しているのか、リンクリストの構築に使用するインスタンスを1つだけ作成しているのかを知る必要があるということです。したがって、のチェックseq is None。ユーザーがシーケンスを渡すと、.__init__()リンクリスト全体が作成されますが、それ以外の場合は、リスト内のリンクとして使用されるインスタンスが1つだけ作成されます。

class link_list(object):
    """a link list class"""
    def __init__(self, seq=None):
        super(link_list, self).__init__()
        if seq is None:
            return
        pdb.set_trace()
        itr = iter(seq)
        try:
            self.value = next(itr)
        except StopIteration:
            self.value = None
            self.next = None
            return
        cur = self
        for value in itr:
            cur.next = link_list()
            cur = cur.next
            cur.value = value
        cur.next = None

l=link_list([])
print l.next is None
l=link_list([1,2,3])
print l.next.next.next is None

まず、シーケンスから新しいイテレータを取得します。次に、。を使用してシーケンスから値を取得しようとしnext()ます。これが失敗した場合、長さゼロのリンクリストがあり、それを返します。これが成功した場合、リンクリストの先頭にその値を使用してから、シーケンスの残りの値をループします。

イテレータを直接操作するのは難しいように思えるかもしれませんが、このようなケースを処理する最もクリーンな方法だと思います。シーケンスから最初のアイテムをプルしてから残りのアイテムをループし、スライスを使用したくない場合です。 (したがって、実際のリストでのみ機能します)。

于 2012-07-02T23:54:58.347 に答える
1
class Item(object):
    '''Linked list'''

    def __new__(cls, lst):
        '''Construct object (allocate the memory)'''
        if lst:
            return super(Item, cls).__new__(cls)

    def __init__(self, lst):
        '''Initialize object (already created)'''
        self.value = lst[0]
        self.next = self.__class__(lst[1:])

    def __repr__(self):
        '''Representate as string'''
        return "%s(%s) -> %s" % (
            self.__class__.__name__,
            self.value,
            repr(self.next)
        )

>>> items = Item([1,2,3])
>>> print items
Item(1) -> Item(2) -> Item(3) -> None
>>> items.next.next.next is None
True
于 2012-07-03T04:26:48.727 に答える