skip to Main Content

I am currently studying CS50’s Introduction to Artificial Intelligence with Python. I’ve encountered a line of code that doesn’t make sense to me and I can’t seem to find any resources online to explain this to me.

def contains_state(self,state):
    return any(node.state == state for node in self.frontier)

This is a method in a Python class. What baffles me is how do I make sense of node.state == state for node in self.frontier?

My understanding of any() is that it checks if any of the element that is being iterated is True but how does the code above work?

Thank you very much for your kind help.

4

Answers


  1. self.frontier is an iterable.

    node.state == state for node in self.frontier iterates thru self.frontier and creates a new list of True and False values based on if the state matches.

    any(...) is returning True if any of that list contains True.

    It’s roughly equivalent to:

    node_states = []
    for node in self.frontier:
        node_states.append(node.state == state)
    
    return any(node_states)
    
    Login or Signup to reply.
  2. There are several things going on here:

    • any() function

    https://beginnersbook.com/2019/03/python-any-function/

    Python any() function accepts iterable (list, tuple, dictionary etc.)
    as an argument and return true if any of the element in iterable is
    true, else it returns false. If iterable is empty then any() method
    returns false.

    • Python iterable

    https://www.pythonlikeyoumeanit.com/Module2_EssentialsOfPython/Iterables.html

    An iterable is any Python object capable of returning its members one
    at a time, permitting it to be iterated over in a for-loop.

    • function’s return value: any(node.state == state for node in self.frontier)

      Returns “true” if any “note.value” in any of the “nodes” in the list “self.frontier” have the same value as input parameter “state”.

    I hope that helps…

    Login or Signup to reply.
  3. The code inside any is a generator object with boolean values (either True or False). While going through the for loop, if any node.state == state, contains_state returns True.

    The advantage of using a generator over a list is that you don’t have to iterate through every element if you find a node whose state is equal to the state you are looking for. Therefore, in some/most cases it will run faster.

    If it goes through the entire loop and none of the nodes’ states equals the state passed to contains_state, the function returns False. You can learn more about generators here.

    Login or Signup to reply.
  4. node.state == state for node in self.frontier is a generator with a __next__ method. When something calls __next__, the generator fetches a value from self.frontier, compares its state variable to state and returns the result. When self.frontier raises StopIteration, that exception is passed to the caller.

    any() is the consumer. It calls __next__ until something is true and returns True. If __next__ raises StopIteration, it returns False.

    Example

    >>> state = 'foo'
    >>> frontier = ['bar', 'bar', 'foo', 'bar']
    >>> gen = (value == state for value in frontier)
    >>> type(gen)
    <class 'generator'>
    >>> gen.__next__()
    False
    >>> gen.__next__()
    False
    >>> gen.__next__()
    True
    >>> gen.__next__()
    False
    >>> gen.__next__()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    >>> 
    >>> any(value == state for value in frontier)
    True
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search