Retr0spect - 1 year ago 66

Python Question

I have started to learn Python. I very confused with one-liner used in this code (5th line in the below code).

Can someone please explain to me how this one liner is working? May be re-write in verbose way?

`multiset = [2, 2, 3, 3, 4, 5, 6, 7, 8, 10]`

x = [0]

deltaSet = set(multiset)

for candidate in deltaSet:

if sum([(abs(candidate-member) in multiset) for member in x]) == len(x):

for member in x:

multiset.remove(abs(candidate-member))

x.append(candidate)

if len(x) == n: break

Thanks!

Answer Source

I believe the line you are looking at is:

```
sum([(abs(candidate-member) in multiset) for member in x])
```

First, there are far too many parenthesis there. Lets get rid of the stuff we don't need:

```
sum(abs(candidate-member) in multiset for member in x)
```

Phew, that's a little better already. Now lets actually look at the expression piece by piece:

```
abs(candidate - member) in multiset
```

This is self explanatory enough ... Is the absolute value of the candidate minus the member in the multiset? If yes, the expression returns `True`

, if not, the expression returns `False`

. Now what are the `member`

? Well, there's one for each thing in the iterable `x`

. So you're summing a bunch of `True`

and `False`

. In python, booleans are subclassed from `int`

(with `True == 1`

and `False == 0`

), the sum is basically counting the number of times that expression we talked about earlier is `True`

.

Then they check if it is equal to the `len(x)`

so basically, the code is checking if the expression is `True`

for *every* member in `x`

. Fortunately, there's a better way to write this in python:

```
all(abs(candidate - member) in multiset for member in x)
```

If this is still confusing, we could rewrite this as a function (lets call it `f(x)`

:

```
def f(x):
"""Equivalent to `all(abs(candidate - member) in multiset for member in x."""
for member in x:
if not abs(candidate - member) in multiset:
return False
return True
```

For some reference reading, in both cases, I've used generator expressions (which are similar to list-comprehensions in syntax and meaning, but they generate the items "yielded" on the fly rather than materializing an entire list at once. They're more memory efficient and faster for some operations. They're particularly useful for cases where you don't need to look at every item to know the result (e.g. this one where a single `False`

is enough to make the entire expression `False`

).