Module 3: Functional programming III Flashcards

- [ ] Iterables, Iterators and Generators, Lazy Computation, Real-World Examples of Functional Programming

1
Q

What is an iterable?

A
  • Iterables act as containers of other objects i.e. collection of items
  • Iterations can be used to access the contained objects individually
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Give me examples of iterables.

A
  • Lists
  • Tuples
  • Dictionaries
  • Strings
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What are ways to create iterables?

A
  • for…in… expressions
  • List comprehension
  • Set comprehension
  • Dictionary comprehension
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What does this code showcase?
myList = [‘blue’, ‘red’, ‘yellow’]
for color in myList:
print(color)

A

for …in… expression

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What is a list comprehension?

A

It is a useful and compact way to create a list based on an operation or condition applied to another iterable

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What does this code show?
colors=[‘red’, ‘blue’, ‘yellow’]

li=[” “+s+” “ for s in colors]

for s in li:
print(s)

A

List comprehension

colors=[‘red’, ‘blue’, ‘yellow’]
#List comprehension:
li=[” “+s+” “ for s in colors]
#Access elements:
for s in li:
print(s)

(set and dict comprehensions look basically the same)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What is an iterator?

A
  • Objects that store a state (normally an index)
    NOT collections
  • An iterator is an object that contains a __next__ method
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What is the relation between an iterable and an iterator?

A

When looping over an iterable, the iterator of that iterable will tell us which item of the collection is the next to be read.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What happens when we iterate over iterable objects?

A

We are implicitly calling the iter() built-in function with the iterable object as an argument
- iter(x) checks if object x has an iter method

  • iter returns an iterator for the iterable
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What does iter() return

A

iter() returns an iterable object

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What does the __next__ method return?

A

Returns the next item stored in a collection. When there are more items left, this method will raise a StopIteration exception, which will be caught by iterating expression.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What does the order of access depend on when using iterators?

A

The order of access (i.e. which object is the next) depends on the type of collection

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What are types of collections?

A
  • Ordered types
  • Unordered types
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Explain ordered types and give examples.

A

The order of access is the same as the insertion order.
e.g. lists, strings, tuples, and dicts

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Explained unordered types and give example.

A

The order of access is unknown to the programmer
e.g. sets

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

mySet=set((5,4,3,2,1))
for s in mySet:
print(s, end=”,”)
Do we know in which order these items will be printed? Why or why not.

A

We don’t know the print order as a set is a unordered type, meaning the order of access is unknown to the programmer.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

myList=[5,4,3,2,1]
for item in myList:
print(item, end=”,”)
Do we know the order in which these items will be printed? Why or why not?

A

We know the order as a list is a ordered types, mening the order of access is the same as the insertion order

18
Q

Give examples of built-in iterators.

A
  • range
  • enumerate
  • map
  • filter
  • zip
19
Q

What is the difference between an iterable and an iterator?

A
  • Iterable objects implement an __iter__ method which results in an iterator
  • Iterator objects implement a __next__ method, which attempt to return the next item in the sequence (until the sequence is exhausted) and also an __iter__ method that returns self
20
Q

Are iterators iterable?

A

Yes. Iterator objects also implement (next to the __next method) __iter__ method that returns self.

21
Q

Can iterables be iterators?

A

No.

22
Q

What is a generator?

A

Generators are one type of iterators.

23
Q

How are generators created?

A
  • Defining a yield statement
    OR
  • Using a generator expression ‘
24
Q

What does this code shocase?
def firstn(n):
num = 0
while num < n:
yield num
num += 1

g=firstn(4)

for n in g:
print(n)

A

firstn has a yield statement,

therefore it ‘returns’ a generator:
def firstn(n):
num = 0
while num < n:
yield num
num += 1

g=firstn(4)

for n in g:
print(n)

25
Q

What is the difference in usage between List comprehensions and Generator expressions?

A

Generators are lazy!! & different brackets

Otherwise similar syntax & usage

26
Q

What is an iterable and give examples?(summary)

A
  • Stores a collection of data that can be looped over
  • Has an __iter__ method to obtain an iterator from the iterable ⇒ this is what allows us to loop over the data!
  • E.g.: lists, strings, tuples, sets, dictionaries, list comprehensions, generators, generator expressions
27
Q

What is an iterator

A
  • Object with a state that indicates next item to return in an iteration
  • Has a __next__ method
  • Can be created with __iter__() or with generator functions
  • E.g.: range, enumerate, generator, generator expressions
28
Q

What happens when we run this code?
mylist=[1, 2, 3]
if mylist[7] > 0 and mylist[0] < 1:
print(“We are here!”)

A

IndexError: list index out of range

29
Q

What happens when we run this code?
mylist=[1, 2, 3]
if mylist[0] < 1 and mylist[7] > 0:
print(“We are here!”)

A

The result of the if expression is False
● Python performs lazy evaluation here: when the left condition is False, the result of the and operator will be False regardless of the right-hand condition. Therefore, Python decides to not evaluate the right part!
● This form of evaluation is also known as
non-strict

30
Q

Does this code work?
if myList is not None and len(myList)>1:
do_something()

A

Yes, the code works even when mylist is None thanks to lazy evaluation.

31
Q

if myList is not None and len(myList)>1:
do_something()
What would happen if mylist was None and we had eager (strict) evaluation (i.e. the Python interpreter evaluates both sides of the and operator)?

A

TypeError: object of type ‘NoneType’ has no len()

32
Q

Why is lazy evaluation useful?

A

It does not require indented conditions

33
Q

Are most evaluations in Python eager(strict) or lazy?

A

Eager(strict).

34
Q

What are eager/strict evaluations and give an example?

A

They go from left to right and evaluate all the elements.
»> mylist=[1, 2, 3]
»> 0 * mylist[1]
0
»> 0 * mylist[7]
IndexError: list index out of range

35
Q

What are operations that use lazy evaluation?

A
  • or ,
  • and ,
  • if-else logical operators
  • generator functions
36
Q

What is a lazy evaluation?

A

Stop evaluation when the outcome is already known.

37
Q

Is the evaluation of generators lazy or strict?

A

Lazy

38
Q

Is the evaluation of list comprehensions lazy or strict?

A

Strict.

39
Q

Can you think of any case in which list comprehension is a better solution?

A
  • While generators save memory and computation time due to lazy evaluation, they are not always preferable.
  • List comprehensions are better when you need immediate access to all elements, random access, or repeated iteration over the data, as generators can only be iterated over once and do not support indexing.
40
Q

What are the pros of generators usage of lazy evaluation?

A
  • Efficiency
  • We only perform operations as we need them
  • Saves memory and computation time
41
Q

When is it ideal to use list/generator comprehensions?

A

List comprehension is useful for smaller datasets where the entire list can be held in memory,
# and you need fast access to elements.
# Generators are ideal for large datasets where memory efficiency is critical.