3

次の例が機能しない理由を理解しようとしています。

class BaseClass(object):
    def __init__(self):
        self.count = 1

    def __iter__(self):
        return self

    def next(self):
        if self.count:
            self.count -= 1
            return self
        else:
            raise StopIteration


class DerivedNO(BaseClass):
    pass


class DerivedO(BaseClass):
    def __init__(self):
        self.new_count = 2
        self.next = self.new_next

    def new_next(self):
        if self.new_count:
            self.new_count -= 1
            return None
        else:
            raise StopIteration


x = DerivedNO()
y = DerivedO()

print x
print list(x)
print y
print list(y)

そしてここに出力があります:

<__main__.DerivedNO object at 0x7fb2af7d1c90>
[<__main__.DerivedNO object at 0x7fb2af7d1c90>]
<__main__.DerivedO object at 0x7fb2af7d1d10>
Traceback (most recent call last):
  File "playground.py", line 41, in <module>
    print list(y)
  File "playground.py", line 11, in next
    if self.count:
AttributeError: 'DerivedO' object has no attribute 'count'

ご覧のとおり、でメソッドDerivedOを割り当てようとしても、新しいメソッドは上書きされません。何故ですか?nextへの単純な呼び出しは正常に機能しますが、反復手法を使用する場合はまったく機能しません。next()__init__

編集:私の質問が完全に明確ではなかったことに気づきました。AttributeErrorは、私が解決しようとしている問題ではありません。しかし、それは私が思っていたようにオンnext()ではBaseClassなく、オンになっていることを示しています。DerivedO

4

2 に答える 2

6

これらのメソッドはCPython内部最適化としてではなくクラスメソッドとして扱われるため、インスタンス__iter__(self)に対してモンキーパッチを適用することはできません(これがなぜであるかについての詳細な理論的根拠については、新しいスタイルのクラスの特別なメソッドルックアップを参照してください)。next(self)

これらのメソッドにモンキーパッチを適用する必要がある場合は、代わりにクラスに直接設定する必要があります。

class DerivedO(BaseClass):
    def __init__(self):
        self.new_count = 2
        self.__class__.next = self.__class__.new_next

    def new_next(self):
        if self.new_count:
            self.new_count -= 1
            return None
        else:
            raise StopIteration

上記は機能します。バインドされたメソッドではなく、バインドされていない関数に設定__class__.nextしたことに注意してください。new_next

于 2012-07-27T12:44:53.860 に答える
-1

属性をDerivedO初期化することはないため、メソッドの実行時にAttributeErrorが発生します。countnext

BaseClass.__init__呼び出されるように調整することで(明示的に、またはを使用してsuper) 、このエラーを回避できます。

class DerivedO(BaseClass):
    def __init__(self):
        super(DerivedO, self).__init__()
        self.new_count = 2

    def next(self):
        if self.new_count:
            self.new_count -= 1
            return None
        else:
            raise StopIteration

また、を定義する代わりに、new_next単にオーバーライド(再定義)することもできますnext

于 2012-07-27T12:24:00.867 に答える