0

Can someone please explain what is going on?

>>> xx = ({1,2}, {2,3}, {3,4}, {4,2})
>>> yy = [x.discard(2) for x in xx]
>>> yy
[None, None, None, None]
>>> xx
({1}, {3}, {3, 4}, {4})
>>> id(xx)
4315823704
>>> id(yy)
4315797064

I'd expected yy to be equal to [{1}, {3}, {3, 4}, {4}] and xx to remain untouched!

vaultah
  • 44,105
  • 12
  • 114
  • 143
Pynoable
  • 13
  • 2
  • 5
    Why would you expect that? `discard` removes the element from `x`, it doesn't return anything. – vaultah May 15 '16 at 16:36
  • @vaultah When I expand the list comprehension out I would have thought it would behave as follows: `yy = [] for y in xx: y = y.discard(2) yy.append(y)` – Pynoable May 15 '16 at 16:39
  • 1
    You can't expect a list comprehension to give you back results if you modify something in place - only the `return` value is logged as a result. You'll have to create a new copy of the dictionaries with the filtered elements and return that. So don't use `discard`. – Akshat Mahajan May 15 '16 at 16:40
  • @AkshatMahajan that is basically the same as above, just without intermediate step of assigning to y – Tadhg McDonald-Jensen May 15 '16 at 16:42
  • Your misunderstanding is due to the fact that `discard` doesn't return anything. So your alternative syntax would *not* work either, because `y` would be None. – Daniel Roseman May 15 '16 at 16:49
  • Mutating methods return None to reduce confusion of methods that return a new object and the ones that modify in place. – Tadhg McDonald-Jensen May 15 '16 at 16:51
  • [`set.discard`](https://docs.python.org/2/library/stdtypes.html#set.discard) is a **mutating method** as in it removes the element from the set, not create a new set with it removed!! – Tadhg McDonald-Jensen May 15 '16 at 16:53

1 Answers1

1

To obtain the result that you want, you could use a list comprehension of the form:

yy = [x - {2} for x in xx]

For example:

>>> xx = ({1,2}, {2,3}, {3,4}, {4,2})
>>> yy = [x - {2} for x in xx]
>>> yy
[{1}, {3}, {3, 4}, {4}]
>>> xx
({1, 2}, {2, 3}, {3, 4}, {2, 4})

Your original example behaves as follows:

>>> xx = ({1,2}, {2,3}, {3,4}, {4,2})
>>> yy = []
>>> for x in xx:
...   # Here, x is a reference to one of the existing sets in xx.
...   # x.discard modifies x in place and returns None.
...   y = x.discard(2)
...   # y is None at this point.
...   yy.append(y)
...
>>> yy
[None, None, None, None]
>>> xx
({1}, {3}, {3, 4}, {4})
Binary Birch Tree
  • 15,140
  • 1
  • 17
  • 13