Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - What's the difference between "in" and "in x for x in"

This is my Python code:

# 1)
if (x not in z for z in y):

# 2)
if (x not in y):

Where y could be a list like:

y = ['1','2','3']

Can somebody explain me the difference between these two sentences? Thank you!

like image 648
peperunas Avatar asked Feb 28 '14 01:02

peperunas


People also ask

What does X for X in python mean?

It means something like "for each x in text, if x.isdigit() is True, add it to the list"

What is the difference between x/y and x/y in Python?

So here we find that both codes are almost similar but still there are difference in the outputs. So the reason behind this is that for many types of objects, x += y will modify the object referred to by x in-place, whereas x = x + y will create a new object and reassign x to it.

What is the meaning of X 2 in Python?

x^2 means "x to the power of 2", i.e. "x squared".


3 Answers

Generator

To begin with, (x not in z for z in y) is a generator statement, and if if is in front of it, it will always return True.

if (x not in z for z in y): # Always returns True

This could be used to see if any or all of the nested iterables contain x.

e.g.

if any(x in z for z in y): # Returns True if any of the z's contain x
if all(x in z for z in y): # Returns True only if all of the z's contain x

So if y is this:

y = ['hello','how','are','you']

then if x is, for example, 'e', then the any comprehension above would return True, but the all comprehension would return False.

Conditional

So here's what going on inside that generator comprehension: if y is a list, and you test with:

(x not in z for z in y)

the z in y must be an iterable in order to test for inclusion, which strings are, but you're only seeing if something is in a string of length one in this case. A better example would be to use integers:

y = [1, 2, 3]

and

if (x not in z for z in y):

would fail, because integers are not iterable, but

if (x not in y):

would succeed because you can test for membership in the actual list.

When you have

y = ['1','2','3']

a similar level of nesting would be:

y = [(1,), (2,), (3,)]

and with

(x not in z for z in y)

you are testing if x is in one of those tuples.

Does that make sense?

like image 53
Russia Must Remove Putin Avatar answered Oct 23 '22 01:10

Russia Must Remove Putin


Let’s start with the simple one first:

if (x not in y):

The parentheses don’t carry any meaning there, so this is equivalent to this:

if x not in y:

The in operator checks if something is contained within something else. In your case, you have a list y, so you are checking if something (x) is not contained within (not in) that list y. So '1' not in y would be False because '1' is an element of y, and '4' not in y would be True because '4' is not an element of y.

The other one is something completely different though:

if (x not in z for z in y)

Here we have a generator expression. Generator expressions are of the format (x for z in y) and are equivalent to this code:

for z in y:
    yield x

You might have heard about list comprehensions before; those are similar but use square brackets instead of parentheses: [x for z in y]. As they return a list, they are a bit easier to understand. They are equivalent to this:

lst = []
for z in y:
    lst.append(x)
return lst

Essentially, you are looping over the elements of y, calling each element in an iteration z and return x for that element. In your case, x is an expression itself: x not in z which is basically the same as above: You are checking if x is not contained within z.

Now, generator expressions are a bit complicated, because they are evaluated when an element is requested from it, so let’s assume for now that we have a list comprehension instead

if [x not in z for z in y]:

So what this does is calculate x not in z for each element z in y. So for your y, the resulting list would be this:

[x not in '1', x not in '2', x not in '3']

With a real x, this would as such result in a list with three boolean values. Now a non-empty list is always trueish, so regardless of the result in this check, the if-check would succeed.

The generator expression will return a generator though, which is a more complex object that a list. It is just as well true-ish though, so your check will also succeed regardless of the individual values.

Now imagine, we want to make sure, that for those three elements in the list, we want all checks to result in True. For that, we can use the all() function which essentially checks if a list—or the values in a generator—contains only true values.

if all(x not in z for z in y):

So this will succeed if x is not contained within any element of the list y. If on the other hand we wanted to check if at least one trueish value is in the list or generator, then we could instead use the any() function.

like image 4
poke Avatar answered Oct 22 '22 23:10

poke


  1. This

    if (x not in z for z in y):
    

    is equivalent to

    if True:
    

    Because

    >>> (x not in z for z in y)
    <generator object <genexpr> at 0x000000E7AE26FB88>
    >>> bool(_)
    True
    
  2. This

    if (x not in y):
    

    Is the same as

    if x not in y:
    

    Which resolves internally to

    if not y.__contains__(x):
    

In the first case, you might have meant to write:

if any(x not in z for z in y):
# same as
if not all(x in z for z in y):

or:

if all(x not in z for z in y):
# same as
if not any(x in z for z in y):
like image 2
Eric Avatar answered Oct 23 '22 00:10

Eric