forked from bslatkin/effectivepython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathitem_29.py
More file actions
executable file
·194 lines (155 loc) · 5.71 KB
/
Copy pathitem_29.py
File metadata and controls
executable file
·194 lines (155 loc) · 5.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#!/usr/bin/env PYTHONHASHSEED=1234 python3
# Copyright 2014-2019 Brett Slatkin, Pearson Education Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Reproduce book environment
import random
random.seed(1234)
import logging
from pprint import pprint
from sys import stdout as STDOUT
# Write all output to a temporary directory
import atexit
import gc
import io
import os
import tempfile
TEST_DIR = tempfile.TemporaryDirectory()
atexit.register(TEST_DIR.cleanup)
# Make sure Windows processes exit cleanly
OLD_CWD = os.getcwd()
atexit.register(lambda: os.chdir(OLD_CWD))
os.chdir(TEST_DIR.name)
def close_open_files():
everything = gc.get_objects()
for obj in everything:
if isinstance(obj, io.IOBase):
obj.close()
atexit.register(close_open_files)
# Example 1
stock = {
"nails": 125,
"screws": 35,
"wingnuts": 8,
"washers": 24,
}
order = ["screws", "wingnuts", "clips"]
# floor division 1,5 =>1
def get_batches(count, size):
return count // size
result = {}#init result as dict
for name in order:
# get defaults to 0 if no values are specified
count = stock.get(name, 0)
#print(count)
# get defaults to 8 if no values are specified
batches = get_batches(count, 8)#size ->8
print(batches)
# if batches is True, then add to result dict key/value => name: batches
if batches:#batches >0 ->true then add new key/value to dict
result[name] = batches
print(result)
# Example 2
# found is a set with comprehension cerate a dict name: batches
# use function get_batches if name not in stock get defaults to 0
# if name in list order then use function get_batches again to get existing batches
# order = ["screws", "wingnuts", "clips"]
found = {#dict comprehension create stucture name/size pair as expression filled by for loop over order by name present in stock
name: get_batches(stock.get(name, 0), 8)#expression part
for name in order
if get_batches(stock.get(name, 0), 8)
}
print(found)
# Example 3
# create has_bag set see "found" set but now for batches of 4 instead of 8
has_bug = {
name: get_batches(stock.get(name, 0), 4)#all element with size 4
for name in order
if get_batches(stock.get(name, 0), 8)#select just the ones with size 8 so found within has_bags
}
print("Expected:", found)
print("Found: ", has_bug)
# Example 4
# use ":=" for assigning value/batches if name is in order
# get default 0 if the name is not in stock returns false else True if in stock
# then found is set {name: batches}
found = {#dict with str/int pair as expression and for loop over list to get elements
name: batches #expression
for name in order
if (batches := get_batches(stock.get(name, 0), 8))#assign return of finc to var with ":="
}
assert found == {"screws": 4, "wingnuts": 1}
print(found)
# Example 5
try:
# test for names in stock where count//10 > 0
# create new variable "tenth" assign if name/size pair in stock > 10 then True
# add to result {name: size/10 >0}
# bring assign to if block if referencing "tenth" variable later in comprehension
result = {
name: (tenth := count // 10) #cut of divide by 10 assign to var as expression for dict comprehension
for name, count in stock.items()
if tenth > 0 #use calculated value ftom str/int pair to filter
}
except:
logging.exception("Expected")
else:
assert False # True then return is empty set
print(result)
print(tenth)
# Example 6
# sort of initialize "tenth" later assign in if block
result = {
name: tenth #str/int pair in dict as expression in dict comprehension
for name, count in stock.items() #for loop over dict
if (tenth := count // 10) > 0}#calculated and assign and filter in one go
print(result)
# Example 7
# create list determine division 2 assign to "last" variable
# loops over values in stock
half = [
(last := count // 2) #assign calculated value to var in expression for list comprehension
for count in stock.values()#for loop over values of name/value pairs in dict
]
print(f"Last item of {half} is {last}")
# Example 8
# leak means variable in expression leaks in the loop else better to have
# error=> variable unknown to loop
for count in stock.values(): # Leaks loop variable loop till last then print
pass
print(f"Last item of {list(stock.values())} is {count}")
# Example 9
# here "count" is not in the same scope as half no leaking of count variable
try:
del count#del var
half = [
count // 2 #expression with count as index in comprehension only ->del in outer scope
for count in stock.values()
]
print(half) # Works
print(count) # Exception because loop variable didn't leak
#NameError: name 'count' is not defined
except:
logging.exception("Expected")
else:
assert False
# Example 10
# see assign values to "batches" in if block return tuple with next statement
# as iterator over "found" tuple
found = (
(name, batches) #expression str/int tuple in tuple comprehension
for name in order #for loop over list
if (batches := get_batches(stock.get(name, 0), 8))#assign value to var for str/int tuple
)
print(next(found))#next needed for next item by generator
print(next(found))#other next needed for other next item by generator