View difference between Paste ID: zBPRJGRF and pU4PbtK2
SHOW: | | - or go back to the newest paste.
1
-----BEGIN PGP SIGNED MESSAGE-----
2
Hash: SHA1
3
4
#!/usr/bin/env python3
5
#
6
# So, I've got some free python training for you! This code works both
7
# with python2 and python3. I love python3's print function, so let's add
8
# it...
9
10
from __future__ import print_function
11
12
# Ok. First thing, did you know about namedtuple? It works as a regular
13
# tuple, but you can access the fields by name (hence "named" tuple).
14
# Besides, it is optimized for producing a large amount of instances.
15
16
from collections import namedtuple
17
18
# It works as a meta-type: you define types by calling a function.
19
Row = namedtuple("Row", "name age city")
20
21
# ...but refer to the documentation (pydoc collections.namedtuple) for
22
# that. Here a proof of how it works:
23
24
r = Row("Luke", 40, "Amsterdam")
25
print("Showing Row:", r)
26
print("Showing fields of the row:", r.name, r.age, r.city)
27
28
# Let's take an hypotetical list of results. This Could be the output of
29
# some stats file, or maybe from a database (even if the database will
30
# probably have some inner type!).
31
32
records = [
33
    Row("Jane", 15, "London"),
34
    Row("Georg", 15, "Berlin"),
35
    Row("Urlika", 20, "Stockholm"),
36
    Row("Johan", 17, "Stockholm"),
37
    Row("Aldo", 9, "Rome"),
38-
    Row("Hans", 17, "Berlin")
38+
    Row("Hans", 17, "Berlin"),
39
    Row("Petra", 21, "Berlin")
40
]
41
42
# About itertools? It's an extremely nice library of python, with useful
43
# lazy-evaluated functions [ https://en.wikipedia.org/wiki/Lazy_evaluation ].
44
# Iterators in general allow to iterate (hence the word) on objects like
45
# tuples or lists ("iterables").
46
47
import itertools as it
48
49
# Iterators are very elegant, and if wisely used they can reduce the
50
# memory footprint of a program, but on the minus side they get consumed:
51
# you cannot use the same iterator twice. Example:
52
53
# I can print lists twice:
54
55
print('-' * 80)
56
print("Records")
57
for r in records:
58
    print("\t", r)
59
print("...second shot:")
60
for r in records:
61
    print("\t", r)
62
print("end.")
63
64
print('-' * 80)
65
66
# But iterators get consumed
67
records_iterator = iter(records)
68
print("Iterated records")
69
for r in records_iterator:
70
    print("\t", r)
71
print("...second shot (will be empty):")
72
for r in records_iterator:
73
    print("\t", r)
74
print("end.")
75
print('-' * 80)
76
77
# Also I'll include the "attrgetter" operator. Quoting the documentation:
78
#
79
#   After, f=attrgetter('name'), the call f(r) returns r.name.
80
81
from operator import attrgetter as aget
82
83
# For example, this is get_city:
84
get_city = aget('city')
85
86
# Since the records are namedtuple with a field called `city`,
87
# `aget('city')` will produce a function returning the `city` field:
88
r = Row("Luke", 40, "Amsterdam")
89
print("The city of Luke is:", get_city(r))
90
91
# Now some interesting use of the groupby function.
92
#
93
# It basically works as the "Group By" operator on SQL: group together
94
# items of a table (in this case an iterator), and allow iteration over
95
# single groups. The only caveat: items of the same group must be
96
# contiguous, as for the "uniq" command of unix, which is often preceded
97
# by the "sort" command, in pipe.
98
#
99
# For instance, let's take the `records` list, we defined previously, and
100
# group the rows by the `city` attribute.  The `get_city` we defined
101
# before turns out to be a good grouping function So, those items have to
102
# be sorted by the relevant field...
103
records_sorted = sorted(records, key=get_city)
104
105
# ...Then we can use the groupby:
106
for city, rows in it.groupby(records_sorted, get_city):
107
    print("City:", city, end="\n\t")
108
    print(*rows, sep="\n\t", end="\n\n")
109
110
# Nice thing: this allows us to do some aggregation (e.g. sum, or average)
111
# quite easily. Want to know the average age by city?
112
for city, rows in it.groupby(records_sorted, get_city):
113
    print(
114
        "City:", city,
115
        "Avg.age:", sum(map(aget('age'), rows)),
116
        end="\n\n"
117
    )
118
119
# Note: sorted() will return *a list*, not an iterator. That's why we can
120
# use the it.groupby() function twice on it. If line 99 were
121
#
122
#   records_sorted = iter(sorted(records, key=get_city))
123
#
124
# Then the second cycle at line 108 would have not worked. Also you may
125
# try to cycle with it.groupby on records instead of records_sorted: you
126
# will see the results! :)
127
128
# Happy hacking.
129
130
-----BEGIN PGP SIGNATURE-----
131
Version: GnuPG v1
132
133-
iQIcBAEBAgAGBQJS3aTyAAoJEC+Zq7a6FN+eueYQALImcxP1jJaRrrxtaLqjAZqf
133+
iQIcBAEBAgAGBQJS3achAAoJEC+Zq7a6FN+eurQP/j43RSd8kTDOsRGWIo2Xfm+U
134-
weYjcOq634NuMg2LFdRUV7KFc0GuW6AClGokXSle9F7hGsJZaxaer1VknkN5vmnw
134+
Ty1j4/GK8OugyWqNjUKoM+jhBMFuFGEINaRtK0PM4UOzlMyKvrFRSVezSvnj0yF6
135-
fzzs6soA+FN3fopjTmVxLXJvxrQNP+gSk4iuFF09KNU/E+UZfkKx5vpA+xg1wvr6
135+
zVPVTxVqRvONAi1+95k6j4CaaVWEZSvn3/jBjS7WfXk2bp1FsPcZfus3LkPQZmkn
136-
R3Bi+jy8mDsz7zHkrv0sDdyIJF9ty6VZe3/afkM3TaaQN7/CRptpkGTJnA9bvkyJ
136+
J6xZfDmhqlxT4AwTHU+lURaCm9U8qTa5oHImPt8HKr8toPuCT3pT8OPo2JLDb5i5
137-
eA9p5NyRD1eO9e6GScUeJ/Btn9sJ1kzfkYxdsLr4cRFSsRf3X0IymgUNOOpAAyH4
137+
+pUE+d3SsFFssRrRl0DgiQMJOFcqNRDv4QMrZHqJvz4MFq58gJxzwyBW0BNmgO/T
138-
+gvyeUw8iowukJD3B0+YTQgfs7A9LUSZNHd+ElmC+eOJxAgmQwuhsxAvXN0I2seI
138+
Pmn7VY37DfZLjMKDWB1Tfw7vVddRj1zezMQP3fwkeMM8koVCTfDsLvq5Mej8MHec
139-
+CuNKmf+zF4TGY3bnQHjE2XBk4Q42m7N+gsN1wsd7t4gK/q5jK8Mf8eh8qvXE5tt
139+
uouV2pht0aFem1OuspOXeaH/l1fUrCIKqG9deO9nZPyQQs9AF/c+/1Nvd126l3/6
140-
H8yLPc6y9kjglFLFzBtrskDKrKZ9M/rRPUJZJJOZ+rrkEAtOPq4JINKfhZL3tOsI
140+
mZOdXQWoX8j3fNwBcZF4UhkQ6xksmvaJXaRGtEInLMjSa8HeCoxRQNqV+yCb8CHP
141-
rYPKlBhbl8uEuy6w1lChsEn+yUE+Tct5XL/jF+hkLzlkWLCO9FB15Ta6XHxK+xff
141+
ecTc5gxLA6N+sip+/5eLi1Joy3ViuCTZr1jZ5Mxis1kGVAFd904jS7HlOOeTPOyY
142-
sssbeFOcarFra7ssKK1Hou8LPeoqkUy5AC2ywnp3oOMU3dk6+qXrG0+ROGp5IxXr
142+
aXjEbhKWPE/HMmiaIMwflnvz4fQDy6K3fGXaHdbo6bUzPClF/jTt1O/We4/LOtcz
143-
0JiEGiykUmXqdqLAeSAwm8H2Ac7U9+8LT5g1FUTpMsvQezfburyUjmDVWLiaKcNE
143+
pkij+MPtFI8eTiXUSuo9Quh/QVc095YMJiHAtS69m0EdyqgbWnRqQmM3lhRnGdcr
144-
z6UCQu37bHVaRM0RmLqX
144+
t2ymjyt6iUxFugniI0AN
145-
=+CMW
145+
=kl1F
146
-----END PGP SIGNATURE-----