Strange behaviour when inheriting from a list in p

2019-06-05 20:37发布

I was fiddling around with inheritance recently and I'm a little confused by the behaviour of the following:

class Foo(list):

    def method(self, thing):
        new = self + [thing]
        print(new)
        self = new
        print(self)

    def method2(self, thing):
        self += [thing]

>>> f = Foo([1, 2, 3, 4, 5])
>>> f.method(10)
[1, 2, 3, 4, 5, 10]
[1, 2, 3, 4, 5, 10]
>>> f
[1, 2, 3, 4, 5]
>>> f.method2(10)
>>> f
[1, 2, 3, 4, 5, 10]

Why does the in-place method method2 work but the first one doesn't?

2条回答
Animai°情兽
2楼-- · 2019-06-05 21:26

Because that's how in-place operators work.

self = self + [thing] creates a new list and put it into the local variable self, overriding the passed one. But it doesn't modify the object itself. Internally, it does self = self.__add__([thing]).

self += [thing], OTOH, modifies the list in-place. Internally it tries self = self.__iadd__([thing]) first. iadd stands for "inplace add". Only if that doesn't exist, self = self.__add__([thing]) is called.

The difference is that __add__() always creates a new object and leaves the others untouched. __iadd__(), however, is supposed to try first to modify the object it operates on. In this case, it returns it so that no change of object occurs, i. e. self refers to the same object as before. Only if this is not possible, it returns a new one which is then assigned.

查看更多
对你真心纯属浪费
3楼-- · 2019-06-05 21:36

list.__add__() (the + operator builtin) creates a new list, while list.__iadd__() (the += operator builtin) modifies the list in place.

查看更多
登录 后发表回答