Reputation: 405
In Python 2.7.x
In [21]: s = set([-1, -1, -1, 0, -1, 0, 0, 0, 0]).remove(-1)
In [22]: type(s)
Out[22]: NoneType
and
In [23]: s = set([-1, -1, -1, 0, -1, 0, 0, 0, 0])
In [24]: type(s)
Out[24]: set
In [25]: s.remove(-1)
In [26]: type(s)
Out[26]: set
In [27]: s
Out[27]: set([0])
Why does function chaining not work as expected in the above example?
Upvotes: 2
Views: 96
Reputation: 239573
s = set([-1, -1, -1, 0, -1, 0, 0, 0, 0])
remove
returns None
. You can confirm that by printing the type of the return value from remove
like this
print type(s.remove(-1))
you will get
<type 'NoneType'>
So, basically you are setting None
to s
.
Upvotes: 2
Reputation: 310049
generally, with python builtins, if the method modifies the object, it returns None
to make it absolutely explicit that the object was modified in place. In this case, set.remove
modifies the set in place, so by convention, it should return None
.
You'll see the same behavior with list.remove
or list.append
or set.add
for example.
This comes as a shock to people coming from different languages where it is common for a method to mutate the object and (effectively) to return self
. It's convenient in that it allows methods to be chained nicely... But, the core python dev's have chosen a different path because they believe (and I agree) that in the long run, it leads to cleaner more obvious code. I would advise you to use python's convention in your own python code (but of course, you're free to disregard that advice completely).
Upvotes: 6
Reputation: 60004
set.remove()
does not return a set with the removed items, it removes them in place. As it does this, the function will return None
. So technically you are doing s = None
in your first example.
Upvotes: 4