This commit is contained in:
adii1823 2021-10-28 17:38:16 +05:30
parent ee641c189f
commit ef37ce0c4e
46 changed files with 524 additions and 0 deletions

View File

@ -0,0 +1,26 @@
# decorate.sort.undecorate.py
from pprint import pprint
students = [
dict(id=0, credits=dict(math=9, physics=6, history=7)),
dict(id=1, credits=dict(math=6, physics=7, latin=10)),
dict(id=2, credits=dict(history=8, physics=9, chemistry=10)),
dict(id=3, credits=dict(math=5, physics=5, geography=7)),
]
def decorate(student):
# create a 2-tuple (sum of credits, student) from student dict
return (sum(student['credits'].values()), student)
pprint(decorate(students[0]))
def undecorate(decorated_student):
# discard sum of credits, return original student dict
return decorated_student[1]
students = sorted(map(decorate, students), reverse=True)
students = list(map(undecorate, students))
pprint(students)

View File

@ -0,0 +1,6 @@
# dictionary.comprehensions.duplicates.py
word = 'Hello'
swaps = {c: c.swapcase() for c in word}
print(swaps) # prints: {'H': 'h', 'e': 'E', 'l': 'L', 'o': 'O'}

View File

@ -0,0 +1,6 @@
# dictionary.comprehensions.positions.py
word = 'Hello'
positions = {c: k for k, c in enumerate(word)}
print(positions) # prints: {'H': 0, 'e': 1, 'l': 3, 'o': 4}

View File

@ -0,0 +1,10 @@
# dictionary.comprehensions.py
from string import ascii_lowercase
lettermap = {c: k for k, c in enumerate(ascii_lowercase, 1)}
# lettermap = dict((c, k) for k, c in enumerate(ascii_lowercase, 1))
from pprint import pprint
pprint(lettermap)

10
ch05/even.squares.py Normal file
View File

@ -0,0 +1,10 @@
# even.squares.py
# using map and filter
sq1 = list(
map(lambda n: n ** 2, filter(lambda n: not n % 2, range(10)))
)
# equivalent, but using list comprehensions
sq2 = [n ** 2 for n in range(10) if not n % 2]
print(sq1, sq1 == sq2) # prints: [0, 4, 16, 36, 64] True

12
ch05/fibonacci.elegant.py Normal file
View File

@ -0,0 +1,12 @@
# fibonacci.elegant.py
def fibonacci(N):
"""Return all fibonacci numbers up to N. """
a, b = 0, 1
while a <= N:
yield a
a, b = b, a + b
print(list(fibonacci(0))) # [0]
print(list(fibonacci(1))) # [0, 1, 1]
print(list(fibonacci(50))) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

14
ch05/fibonacci.first.py Normal file
View File

@ -0,0 +1,14 @@
# fibonacci.first.py
def fibonacci(N):
"""Return all fibonacci numbers up to N. """
result = [0]
next_n = 1
while next_n <= N:
result.append(next_n)
next_n = sum(result[-2:])
return result
print(fibonacci(0)) # [0]
print(fibonacci(1)) # [0, 1, 1]
print(fibonacci(50)) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

16
ch05/fibonacci.second.py Normal file
View File

@ -0,0 +1,16 @@
# fibonacci.second.py
def fibonacci(N):
"""Return all fibonacci numbers up to N. """
yield 0
if N == 0:
return
a = 0
b = 1
while b <= N:
yield b
a, b = b, a + b
print(list(fibonacci(0))) # [0]
print(list(fibonacci(1))) # [0, 1, 1]
print(list(fibonacci(50))) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

10
ch05/filter.py Normal file
View File

@ -0,0 +1,10 @@
# filter.py
# This is not a valid Python module - Don't run it.
>>> test = [2, 5, 8, 0, 0, 1, 0]
>>> list(filter(None, test))
[2, 5, 8, 1]
>>> list(filter(lambda x: x, test)) # equivalent to previous one
[2, 5, 8, 1]
>>> list(filter(lambda x: x > 4, test)) # keep only items > 4
[5, 8]

View File

@ -0,0 +1,12 @@
# first.n.squares.manual.method.py
def get_squares_gen(n):
for x in range(n):
yield x ** 2
squares = get_squares_gen(3)
print(squares.__next__()) # prints: 0
print(squares.__next__()) # prints: 1
print(squares.__next__()) # prints: 4
# the following raises StopIteration, the generator is exhausted,
# any further call to next will keep raising StopIteration
print(squares.__next__())

View File

@ -0,0 +1,14 @@
# first.n.squares.manual.py
def get_squares_gen(n):
for x in range(n):
yield x ** 2
squares = get_squares_gen(4) # this creates a generator object
print(squares) # <generator object get_squares_gen at 0x10dd...>
print(next(squares)) # prints: 0
print(next(squares)) # prints: 1
print(next(squares)) # prints: 4
print(next(squares)) # prints: 9
# the following raises StopIteration, the generator is exhausted,
# any further call to next will keep raising StopIteration
print(next(squares))

12
ch05/first.n.squares.py Normal file
View File

@ -0,0 +1,12 @@
# first.n.squares.py
def get_squares(n): # classic function approach
return [x ** 2 for x in range(n)]
print(get_squares(10))
def get_squares_gen(n): # generator approach
for x in range(n):
yield x ** 2 # we yield, we don't return
print(list(get_squares_gen(10)))

7
ch05/functions.py Normal file
View File

@ -0,0 +1,7 @@
# functions.py
def gcd(a, b):
"""Calculate the Greatest Common Divisor of (a, b). """
while b != 0:
a, b = b, a % b
return a

5
ch05/gen.filter.py Normal file
View File

@ -0,0 +1,5 @@
# gen.filter.py
cubes = [x**3 for x in range(10)]
odd_cubes1 = filter(lambda cube: cube % 2, cubes)
odd_cubes2 = (cube for cube in cubes if cube % 2)

14
ch05/gen.map.filter.py Normal file
View File

@ -0,0 +1,14 @@
# gen.map.filter.py
# finds the cubes of all multiples of 3 or 5 below N
N = 20
cubes1 = map(
lambda n: (n, n**3),
filter(lambda n: n % 3 == 0 or n % 5 == 0, range(N))
)
cubes2 = (
(n, n**3) for n in range(N) if n % 3 == 0 or n % 5 == 0)
print(list(cubes1))
print(list(cubes2))

6
ch05/gen.map.py Normal file
View File

@ -0,0 +1,6 @@
# gen.map.py
def adder(*n):
return sum(n)
s1 = sum(map(adder, range(100), range(1, 101)))
s2 = sum(adder(*n) for n in zip(range(100), range(1, 101)))

View File

@ -0,0 +1,11 @@
# gen.send.preparation.py
def counter(start=0):
n = start
while True:
yield n
n += 1
c = counter()
print(next(c)) # prints: 0
print(next(c)) # prints: 1
print(next(c)) # prints: 2

View File

@ -0,0 +1,14 @@
# gen.send.preparation.stop.py
stop = False
def counter(start=0):
n = start
while not stop:
yield n
n += 1
c = counter()
print(next(c)) # prints: 0
print(next(c)) # prints: 1
stop = True
print(next(c)) # raises StopIteration

15
ch05/gen.send.py Normal file
View File

@ -0,0 +1,15 @@
# gen.send.py
def counter(start=0):
n = start
while True:
result = yield n # A
print(type(result), result) # B
if result == 'Q':
break
n += 1
c = counter()
print(next(c)) # C
print(c.send('Wow!')) # D
print(next(c)) # E
print(c.send('Q')) # F

7
ch05/gen.yield.for.py Normal file
View File

@ -0,0 +1,7 @@
# gen.yield.for.py
def print_squares(start, end):
for n in range(start, end):
yield n ** 2
for n in print_squares(2, 5):
print(n)

6
ch05/gen.yield.from.py Normal file
View File

@ -0,0 +1,6 @@
# gen.yield.from.py
def print_squares(start, end):
yield from (n ** 2 for n in range(start, end))
for n in print_squares(2, 5):
print(n)

15
ch05/gen.yield.return.py Normal file
View File

@ -0,0 +1,15 @@
# gen.yield.return.py
def geometric_progression(a, q):
k = 0
while True:
result = a * q**k
if result <= 100000:
yield result
else:
return
k += 1
for n in geometric_progression(2, 5):
print(n)

View File

@ -0,0 +1,17 @@
# generator.expressions.py
# This is not a valid Python module - Don't run it.
>>> cubes = [k**3 for k in range(10)] # regular list
>>> cubes
[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
>>> type(cubes)
<class 'list'>
>>> cubes_gen = (k**3 for k in range(10)) # create as generator
>>> cubes_gen
<generator object <genexpr> at 0x103fb5a98>
>>> type(cubes_gen)
<class 'generator'>
>>> list(cubes_gen) # this will exhaust the generator
[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
>>> list(cubes_gen) # nothing more to give
[]

7
ch05/list.iterable.py Normal file
View File

@ -0,0 +1,7 @@
# list.iterable.py
# this code won't run
>>> range(7)
range(0, 7)
>>> list(range(7)) # put all elements in a list to view them
[0, 1, 2, 3, 4, 5, 6]

18
ch05/map.example.py Normal file
View File

@ -0,0 +1,18 @@
# map.example.py
# This is not a valid Python module - Don't run it.
>>> map(lambda *a: a, range(3)) # 1 iterable
<map object at 0x10acf8f98> # Not useful! Let's use list
>>> list(map(lambda *a: a, range(3))) # 1 iterable
[(0,), (1,), (2,)]
>>> list(map(lambda *a: a, range(3), 'abc')) # 2 iterables
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> list(map(lambda *a: a, range(3), 'abc', range(4, 7))) # 3
[(0, 'a', 4), (1, 'b', 5), (2, 'c', 6)]
>>> # map stops at the shortest iterator
>>> list(map(lambda *a: a, (), 'abc')) # empty tuple is shortest
[]
>>> list(map(lambda *a: a, (1, 2), 'abc')) # (1, 2) shortest
[(1, 'a'), (2, 'b')]
>>> list(map(lambda *a: a, (1, 2, 3, 4), 'abc')) # 'abc' shortest
[(1, 'a'), (2, 'b'), (3, 'c')]

9
ch05/maxims.py Normal file
View File

@ -0,0 +1,9 @@
# maxims.py
# This is not a valid Python module - Don't run it.
>>> a = [5, 9, 2, 4, 7]
>>> b = [3, 7, 1, 9, 2]
>>> c = [6, 8, 0, 5, 3]
>>> maxs = map(lambda n: max(*n), zip(a, b, c))
>>> list(maxs)
[6, 9, 2, 9, 7]

10
ch05/pairs.for.loop.py Normal file
View File

@ -0,0 +1,10 @@
# pairs.for.loop.py
items = 'ABCD'
pairs = []
for a in range(len(items)):
for b in range(a, len(items)):
pairs.append((items[a], items[b]))
print(pairs)

View File

@ -0,0 +1,7 @@
# pairs.list.comprehension.py
items = 'ABCD'
pairs = [(items[a], items[b])
for a in range(len(items)) for b in range(a, len(items))]
print(pairs)

20
ch05/performance.map.py Normal file
View File

@ -0,0 +1,20 @@
# performance.map.py
from time import time
mx = 2 * 10 ** 7
t = time()
absloop = []
for n in range(mx):
absloop.append(abs(n))
print('for loop: {:.4f} s'.format(time() - t))
t = time()
abslist = [abs(n) for n in range(mx)]
print('list comprehension: {:.4f} s'.format(time() - t))
t = time()
absmap = list(map(abs, range(mx)))
print('map: {:.4f} s'.format(time() - t))
print(absloop == abslist == absmap)

29
ch05/performance.py Normal file
View File

@ -0,0 +1,29 @@
# performance.py
from time import time
mx = 5000
t = time() # start time for the for loop
floop = []
for a in range(1, mx):
for b in range(a, mx):
floop.append(divmod(a, b))
print('for loop: {:.4f} s'.format(time() - t)) # elapsed time
t = time() # start time for the list comprehension
compr = [
divmod(a, b) for a in range(1, mx) for b in range(a, mx)]
print('list comprehension: {:.4f} s'.format(time() - t))
t = time() # start time for the generator expression
gener = list(
divmod(a, b) for a in range(1, mx) for b in range(a, mx))
print('generator expression: {:.4f} s'.format(time() - t))
# verify correctness of results and number of items in each list
print(
floop == compr == gener, len(floop), len(compr), len(gener)
)

View File

@ -0,0 +1,10 @@
# pythagorean.triple.comprehension.py
from math import sqrt
# this step is the same as before
mx = 10
triples = [(a, b, sqrt(a**2 + b**2))
for a in range(1, mx) for b in range(a, mx)]
# here we combine filter and map in one CLEAN list comprehension
triples = [(a, b, int(c)) for a, b, c in triples if c.is_integer()]
print(triples) # prints: [(3, 4, 5), (6, 8, 10)]

View File

@ -0,0 +1,17 @@
# pythagorean.triple.generation.for.py
from functions import gcd
def gen_triples(N):
for m in range(1, int(N**.5) + 1): # 1
for n in range(1, m): # 2
if (m - n) % 2 and gcd(m, n) == 1: # 3
c = m**2 + n**2 # 4
if c <= N: # 5
a = m**2 - n**2 # 6
b = 2 * m * n # 7
yield (a, b, c) # 8
triples = sorted(gen_triples(50), key=sum) # 9
print(triples)

View File

@ -0,0 +1,17 @@
# pythagorean.triple.generation.py
from functions import gcd
N = 50
triples = sorted( # 1
((a, b, c) for a, b, c in ( # 2
((m**2 - n**2), (2 * m * n), (m**2 + n**2)) # 3
for m in range(1, int(N**.5) + 1) # 4
for n in range(1, m) # 5
if (m - n) % 2 and gcd(m, n) == 1 # 6
) if c <= N), key=sum # 7
)
print(triples)

View File

@ -0,0 +1,13 @@
# pythagorean.triple.int.py
from math import sqrt
mx = 10
triples = [(a, b, sqrt(a**2 + b**2))
for a in range(1, mx) for b in range(a, mx)]
triples = filter(lambda triple: triple[2].is_integer(), triples)
# this will make the third number in the tuples integer
triples = list(
map(lambda triple: triple[:2] + (int(triple[2]), ), triples))
print(triples) # prints: [(3, 4, 5), (6, 8, 10)]

View File

@ -0,0 +1,12 @@
# pythagorean.triple.py
from math import sqrt
# this will generate all possible pairs
mx = 10
triples = [(a, b, sqrt(a**2 + b**2))
for a in range(1, mx) for b in range(a, mx)]
# this will filter out all non pythagorean triples
triples = list(
filter(lambda triple: triple[2].is_integer(), triples))
print(triples) # prints: [(3, 4, 5.0), (6, 8, 10.0)]

View File

@ -0,0 +1,10 @@
# pythagorean.triple.walrus.py
from math import sqrt
# this step is the same as before
mx = 10
# We can combine generating and filtering in one comprehension
triples = [(a, b, int(c))
for a in range(1, mx) for b in range(a, mx)
if (c := sqrt(a**2 + b**2)).is_integer()]
print(triples) # prints: [(3, 4, 5), (6, 8, 10)]

6
ch05/scopes.for.py Normal file
View File

@ -0,0 +1,6 @@
# scopes.for.py
s = 0
for A in range(5):
s += A
print(A) # prints: 4
print(globals())

3
ch05/scopes.noglobal.py Normal file
View File

@ -0,0 +1,3 @@
# scopes.noglobal.py
ex1 = [A for A in range(5)]
print(A) # breaks: NameError: name 'A' is not defined

18
ch05/scopes.py Normal file
View File

@ -0,0 +1,18 @@
# scopes.py
A = 100
ex1 = [A for A in range(5)]
print(A) # prints: 100
ex2 = list(A for A in range(5))
print(A) # prints: 100
ex3 = {A: 2 * A for A in range(5)}
print(A) # prints: 100
ex4 = {A for A in range(5)}
print(A) # prints: 100
s = 0
for A in range(5):
s += A
print(A) # prints: 4

View File

@ -0,0 +1,7 @@
# set.comprehensions.py
word = 'Hello'
letters1 = {c for c in word}
letters2 = set(c for c in word)
print(letters1) # prints: {'H', 'o', 'e', 'l'}
print(letters1 == letters2) # prints: True

View File

@ -0,0 +1,5 @@
# squares.comprehension.py
# This is not a valid Python module - Don't run it.
>>> [n ** 2 for n in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

15
ch05/squares.map.py Normal file
View File

@ -0,0 +1,15 @@
# squares.map.py
# This is not a valid Python module - Don't run it.
# If you code like this you are not a Python dev! ;)
>>> squares = []
>>> for n in range(10):
... squares.append(n ** 2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# This is better, one line, nice and readable
>>> squares = map(lambda n: n**2, range(10))
>>> list(squares)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

6
ch05/squares.py Normal file
View File

@ -0,0 +1,6 @@
# squares.py
def square1(n):
return n ** 2 # squaring through the power operator
def square2(n):
return n * n # squaring through multiplication

5
ch05/sum.example.2.py Normal file
View File

@ -0,0 +1,5 @@
# sum.example.2.py
s = sum([n**2 for n in range(10**9)]) # this is killed
s = sum(n**2 for n in range(10**9)) # this succeeds
print(s) # prints: 333333332833333333500000000

6
ch05/sum.example.py Normal file
View File

@ -0,0 +1,6 @@
# sum.example.py
s1 = sum([n**2 for n in range(10**6)])
s2 = sum((n**2 for n in range(10**6)))
s3 = sum(n**2 for n in range(10**6))
print(s1==s2==s3)

9
ch05/zip.grades.py Normal file
View File

@ -0,0 +1,9 @@
# zip.grades.py
# This is not a valid Python module - Don't run it.
>>> grades = [18, 23, 30, 27]
>>> avgs = [22, 21, 29, 24]
>>> list(zip(avgs, grades))
[(22, 18), (21, 23), (29, 30), (24, 27)]
>>> list(map(lambda *a: a, avgs, grades)) # equivalent to zip
[(22, 18), (21, 23), (29, 30), (24, 27)]