Python Comprehensions: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(18 intermediate revisions by the same user not shown)
Line 3: Line 3:
=TODO=
=TODO=
<font color=darkkhaki>
<font color=darkkhaki>
* PROCESS [[IPy]] Comprehensions Page 84.
* PROCESS [[PyOOP]] "Comprehensions" + "List comprehensions" + "Set and dictionary comprehensions"
* PROCESS [[PyOOP]] "Comprehensions" + "List comprehensions" + "Set and dictionary comprehensions"
</font>
</font>


=Overview=
=Overview=
A comprehension is a compact way of creating a data structure from one or more iterators.  
A comprehension is a compact way of creating a data structure from one or more iterators. They are essentially loops with a more compact syntax.


===List Comprehensions===
===List Comprehensions===
A list comprehension produces a list from an [[Python_Language#Iterable_Types|iterable type]] by applying an expression to each of the elements, and optionally a condition. The iterable instance must be indeed iterable, otherwise we get an error message, shown below. So <code>None</code> does not work, it produces a runtime error.
<font size=-1>
TypeError: 'NoneType' object is not iterable
</font>
====Simple List Comprehension====
<syntaxhighlight lang='py'>
[<expression> for <var> in <iterable>]
</syntaxhighlight>
The list comprehension moves the loop inside square brackets.
This example iterates over a list of custom object instances and produces a comma-separated list of their <code>__str__()</code> representations, which printing the list with <code>print()</code> does not do:
<syntaxhighlight lang='py'>
class C:
  def __init__(self, i):
    self.i = i
  def __str__(self):
    return str(self.i)
l = [C(1), C(2), C(3)]
</syntaxhighlight>
<syntaxhighlight lang='py'>
print(l)
</syntaxhighlight>
displays:
<syntaxhighlight lang='text'>
[<__main__.C object at 0x102f06b20>, <__main__.C object at 0x1030159d0>, <__main__.C object at 0x10302c9a0>]
</syntaxhighlight>
The following list comprehension:
<syntaxhighlight lang='py'>
print(', '.join([str(i) for i in l]))
</syntaxhighlight>
displays:
<syntaxhighlight lang='text'>
1, 2, 3
</syntaxhighlight>
====Conditional List Comprehension====
<syntaxhighlight lang='py'>
[<expression> for <var> in <iterable> if <condition>]
</syntaxhighlight>
An example of a conditional list comprehension is to generate a list of even numbers from a list of numbers:
<syntaxhighlight lang='py'>
l = list(range(10))
print(l)
</syntaxhighlight>
displays:
<syntaxhighlight lang='text'>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
</syntaxhighlight>
To get the even numbers:
<syntaxhighlight lang='py'>
l2 = [i for i in l if i % 2 == 0]
print(l2)
</syntaxhighlight>
displays:
<syntaxhighlight lang='text'>
[0, 2, 4, 6, 8]
</syntaxhighlight>
====Nested List Comprehensions====
Just as there can be nested loops, there can be more than on set of <code>for ...</code> clauses.
<syntaxhighlight lang='py'>
rows = range(1, 4)
cols = range(1, 3)
cells = [(row, col) for row in rows for col in cols]
</syntaxhighlight>
====Use Comprehensions for Side Effects====
The purpose of a comprehension is to generate a list from another list. However, it can be also used to exercise side effects on the elements. The result list is discarded.
<syntaxhighlight lang='py'>
class Box:
    def __init__(self):
        self.color = None
    def paint(self, value):
        self.color = value
boxes = [Box(), Box(), Box()]
[b.paint('blue') for b in boxes]
for b in boxes:
    assert b.color == 'blue'
</syntaxhighlight>
===Dictionary Comprehensions===
<font color=darkkhaki>
* PROCESS [[IPy]] Comprehensions Page 87.
</font>
A dictionary comprehension starts from a list, and for each element of the list, generates a key and a value, which are then inserted in the dictionary. The key and the value are introduced with the <code>(k, v)</code> syntax:
<syntaxhighlight lang='py'>
l = ['a', 'b', 'c']
d = dict([(k, k.upper()) for k in l])
print(d)
</syntaxhighlight>
will print:
<syntaxhighlight lang='text'>
{'a': 'A', 'b': 'B', 'c': 'C'}
</syntaxhighlight>
===Set Comprehensions===
<font color=darkkhaki>
* PROCESS [[IPy]] Comprehensions Page 87.
</font>
===Generator Comprehensions===
<font color=darkkhaki>
* PROCESS [[IPy]] Comprehensions Page 88.
</font>

Latest revision as of 17:19, 28 January 2023

Internal

TODO

  • PROCESS PyOOP "Comprehensions" + "List comprehensions" + "Set and dictionary comprehensions"

Overview

A comprehension is a compact way of creating a data structure from one or more iterators. They are essentially loops with a more compact syntax.

List Comprehensions

A list comprehension produces a list from an iterable type by applying an expression to each of the elements, and optionally a condition. The iterable instance must be indeed iterable, otherwise we get an error message, shown below. So None does not work, it produces a runtime error.

TypeError: 'NoneType' object is not iterable

Simple List Comprehension

[<expression> for <var> in <iterable>]

The list comprehension moves the loop inside square brackets. This example iterates over a list of custom object instances and produces a comma-separated list of their __str__() representations, which printing the list with print() does not do:

class C:
  def __init__(self, i):
    self.i = i 
  def __str__(self):
    return str(self.i)

l = [C(1), C(2), C(3)]
print(l)

displays:

[<__main__.C object at 0x102f06b20>, <__main__.C object at 0x1030159d0>, <__main__.C object at 0x10302c9a0>]

The following list comprehension:

print(', '.join([str(i) for i in l]))

displays:

1, 2, 3

Conditional List Comprehension

[<expression> for <var> in <iterable> if <condition>]

An example of a conditional list comprehension is to generate a list of even numbers from a list of numbers:

l = list(range(10))
print(l)

displays:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

To get the even numbers:

l2 = [i for i in l if i % 2 == 0]
print(l2)

displays:

[0, 2, 4, 6, 8]

Nested List Comprehensions

Just as there can be nested loops, there can be more than on set of for ... clauses.

rows = range(1, 4)
cols = range(1, 3)
cells = [(row, col) for row in rows for col in cols]

Use Comprehensions for Side Effects

The purpose of a comprehension is to generate a list from another list. However, it can be also used to exercise side effects on the elements. The result list is discarded.

class Box:
    def __init__(self):
        self.color = None

    def paint(self, value):
        self.color = value

boxes = [Box(), Box(), Box()]

[b.paint('blue') for b in boxes]

for b in boxes:
    assert b.color == 'blue'

Dictionary Comprehensions

  • PROCESS IPy Comprehensions Page 87.

A dictionary comprehension starts from a list, and for each element of the list, generates a key and a value, which are then inserted in the dictionary. The key and the value are introduced with the (k, v) syntax:

l = ['a', 'b', 'c']
d = dict([(k, k.upper()) for k in l])
print(d)

will print:

{'a': 'A', 'b': 'B', 'c': 'C'}

Set Comprehensions

  • PROCESS IPy Comprehensions Page 87.

Generator Comprehensions

  • PROCESS IPy Comprehensions Page 88.