Skip to content

Commit 174e952

Browse files
committed
update from Atlas
1 parent 6911136 commit 174e952

File tree

14 files changed

+426
-10
lines changed

14 files changed

+426
-10
lines changed

classes/vector_v3.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,8 @@ def __getattr__(self, name):
211211
return self._components[pos]
212212
msg = '{.__name__!r} object has no attribute {!r}' # <5>
213213
raise AttributeError(msg.format(cls, name))
214-
215214
# END VECTOR_V3_GETATTR
215+
216216
# BEGIN VECTOR_V3_SETATTR
217217
def __setattr__(self, name, value):
218218
cls = type(self)

descriptors/bulkfood_v1.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
A line item for a bulk food order has description, weight and price fields.
3+
A ``subtotal`` method gives the total price for that line item::
4+
5+
>>> raisins = LineItem('Golden raisins', 10, 6.95)
6+
>>> raisins.weight, raisins.description, raisins.price
7+
(10, 'Golden raisins', 6.95)
8+
>>> raisins.subtotal()
9+
69.5
10+
11+
But, without validation, these public attributes can cause trouble::
12+
13+
# BEGIN LINEITEM_PROBLEM_V1
14+
15+
>>> raisins = LineItem('Golden raisins', 10, 6.95)
16+
>>> raisins.subtotal()
17+
69.5
18+
>>> raisins.weight = -20
19+
>>> raisins.subtotal()
20+
-139.0
21+
22+
# END LINEITEM_PROBLEM_V1
23+
24+
"""
25+
26+
27+
# BEGIN LINEITEM_V1
28+
class LineItem:
29+
30+
def __init__(self, description, weight, price):
31+
self.description = description
32+
self.weight = weight
33+
self.price = price
34+
35+
def subtotal(self):
36+
return self.weight * self.price
37+
# END LINEITEM_V1

descriptors/bulkfood_v2.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""
2+
3+
A line item for a bulk food order has description, weight and price fields::
4+
5+
>>> raisins = LineItem('Golden raisins', 10, 6.95)
6+
>>> raisins.weight, raisins.description, raisins.price
7+
(10, 'Golden raisins', 6.95)
8+
9+
A ``subtotal`` method gives the total price for that line item::
10+
11+
>>> raisins.subtotal()
12+
69.5
13+
14+
The weight of a ``LineItem`` must be greater than 0::
15+
16+
>>> raisins.weight = -20
17+
Traceback (most recent call last):
18+
...
19+
ValueError: value must be > 0
20+
21+
No change was made::
22+
23+
>>> raisins.weight
24+
10
25+
26+
The check is also performed on instantiation::
27+
28+
>>> walnuts = LineItem('walnuts', 0, 10.00)
29+
Traceback (most recent call last):
30+
...
31+
ValueError: value must be > 0
32+
33+
The proteced attribute can still be accessed if needed for some reason, such as
34+
white box testing)::
35+
36+
>>> raisins._LineItem__weight
37+
10
38+
39+
"""
40+
41+
42+
# BEGIN LINEITEM_V2
43+
class LineItem:
44+
45+
def __init__(self, description, weight, price):
46+
self.description = description
47+
self.weight = weight # <1>
48+
self.price = price
49+
50+
def subtotal(self):
51+
return self.weight * self.price
52+
53+
@property # <2>
54+
def weight(self): # <3>
55+
return self.__weight # <4>
56+
57+
@weight.setter # <5>
58+
def weight(self, value):
59+
if value > 0:
60+
self.__weight = value # <6>
61+
else:
62+
raise ValueError('value must be > 0') # <7>
63+
# END LINEITEM_V2

descriptors/bulkfood_v3.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
3+
A line item for a bulk food order has description, weight and price fields::
4+
5+
>>> raisins = LineItem('Golden raisins', 10, 6.95)
6+
>>> raisins.weight, raisins.description, raisins.price
7+
(10, 'Golden raisins', 6.95)
8+
9+
A ``subtotal`` method gives the total price for that line item::
10+
11+
>>> raisins.subtotal()
12+
69.5
13+
14+
The weight of a ``LineItem`` must be greater than 0::
15+
16+
>>> raisins.weight = -20
17+
Traceback (most recent call last):
18+
...
19+
ValueError: value must be > 0
20+
21+
Negative or 0 price is not acceptable either::
22+
23+
>>> truffle = LineItem('White truffle', 100, 0)
24+
Traceback (most recent call last):
25+
...
26+
ValueError: value must be > 0
27+
28+
29+
No change was made::
30+
31+
>>> raisins.weight
32+
10
33+
34+
"""
35+
36+
# BEGIN LINEITEM_V3
37+
class Quantity: # <1>
38+
39+
def __init__(self, storage_name):
40+
self.storage_name = storage_name # <2>
41+
42+
def __set__(self, instance, value): # <3>
43+
if value > 0:
44+
instance.__dict__[self.storage_name] = value # <4>
45+
else:
46+
raise ValueError('value must be > 0')
47+
48+
49+
class LineItem:
50+
weight = Quantity('weight') # <5>
51+
price = Quantity('price') # <6>
52+
53+
def __init__(self, description, weight, price): # <7>
54+
self.description = description
55+
self.weight = weight
56+
self.price = price
57+
58+
def subtotal(self):
59+
return self.weight * self.price
60+
# END LINEITEM_V3

descriptors/bulkfood_v3_broken.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""
2+
WARNING: Broken implementation for demonstration purposes.
3+
4+
A line item for a bulk food order has description, weight and price fields::
5+
6+
>>> raisins = LineItem('Golden raisins', 10, 6.95)
7+
>>> raisins.weight, raisins.description, raisins.price
8+
(10, 'Golden raisins', 6.95)
9+
10+
A ``subtotal`` method gives the total price for that line item::
11+
12+
>>> raisins.subtotal()
13+
69.5
14+
15+
The weight of a ``LineItem`` must be greater than 0::
16+
17+
>>> raisins.weight = -20
18+
Traceback (most recent call last):
19+
...
20+
ValueError: value must be > 0
21+
22+
Negative or 0 price is not acceptable either::
23+
24+
>>> truffle = LineItem('White truffle', 100, 0)
25+
Traceback (most recent call last):
26+
...
27+
ValueError: value must be > 0
28+
29+
30+
No change was made::
31+
32+
>>> raisins.weight
33+
10
34+
35+
"""
36+
37+
class Quantity:
38+
39+
def __init__(self, storage_name):
40+
self.storage_name = storage_name
41+
42+
def __set__(self, instance, value):
43+
if value > 0:
44+
instance.__dict__[self.storage_name] = value
45+
else:
46+
raise ValueError('value must be > 0')
47+
48+
49+
class LineItem:
50+
weight = Quantity('weight')
51+
price = Quantity('weight') # <-- this is the bug discussed in the book
52+
53+
def __init__(self, description, weight, price):
54+
self.description = description
55+
self.weight = weight
56+
self.price = price
57+
58+
def subtotal(self):
59+
return self.weight * self.price

descriptors/bulkfood_v4.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""
2+
3+
A line item for a bulk food order has description, weight and price fields::
4+
5+
>>> raisins = LineItem('Golden raisins', 10, 6.95)
6+
>>> raisins.weight, raisins.description, raisins.price
7+
(10, 'Golden raisins', 6.95)
8+
9+
A ``subtotal`` method gives the total price for that line item::
10+
11+
>>> raisins.subtotal()
12+
69.5
13+
14+
The weight of a ``LineItem`` must be greater than 0::
15+
16+
>>> raisins.weight = -20
17+
Traceback (most recent call last):
18+
...
19+
ValueError: value must be > 0
20+
21+
No change was made::
22+
23+
>>> raisins.weight
24+
10
25+
26+
The value of the attributes managed by the descriptors are stored in
27+
alternate attributes, created by the descriptors in each ``LineItem``
28+
instance::
29+
30+
>>> raisins = LineItem('Golden raisins', 10, 6.95)
31+
>>> dir(raisins) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
32+
['_Quantity_0', '_Quantity_1', '__class__', ...
33+
'description', 'price', 'subtotal', 'weight']
34+
>>> raisins._Quantity_0
35+
10
36+
>>> raisins._Quantity_1
37+
6.95
38+
39+
"""
40+
41+
42+
# BEGIN LINEITEM_V4
43+
class Quantity:
44+
__counter = 0 # <1>
45+
46+
def __init__(self):
47+
cls = self.__class__ # <2>
48+
prefix = cls.__name__ # <3>
49+
index = cls.__counter # <4>
50+
self.storage_name = '_{}_{}'.format(prefix, index) # <5>
51+
cls.__counter += 1 # <6>
52+
53+
def __get__(self, instance, owner): # <7>
54+
return getattr(instance, self.storage_name) # <8>
55+
56+
def __set__(self, instance, value): # <9>
57+
if value > 0:
58+
setattr(instance, self.storage_name, value) # <10>
59+
else:
60+
raise ValueError('value must be > 0')
61+
62+
63+
class LineItem:
64+
weight = Quantity() # <11>
65+
price = Quantity()
66+
67+
def __init__(self, description, weight, price):
68+
self.description = description
69+
self.weight = weight
70+
self.price = price
71+
72+
def subtotal(self):
73+
return self.weight * self.price
74+
# END LINEITEM_V4

metaprog/spreadsheet.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
Demonstration::
77
88
>>> from math import sin, pi
9-
>>> ss = Spreadsheet(sin=sin, pi=pi, abs=abs)
9+
>>> ss = Spreadsheet(sin=sin, pi=pi)
1010
>>> ss['a1'] = '-5'
1111
>>> ss['a2'] = 'a1*6'
1212
>>> ss['a3'] = 'a2*7'
@@ -20,11 +20,6 @@
2020
>>> ss['c1'] = 'abs(a2)'
2121
>>> ss['c1']
2222
30
23-
>>> ss['c2'] = 'len(a2)'
24-
>>> ss['c2']
25-
Traceback (most recent call last):
26-
...
27-
NameError: name 'len' is not defined
2823
>>> ss['d1'] = '3*'
2924
>>> ss['d1']
3025
Traceback (most recent call last):
@@ -37,8 +32,7 @@ class Spreadsheet:
3732

3833
def __init__(self, **tools):
3934
self._cells = {}
40-
self._tools = {'__builtins__' : {}}
41-
self._tools.update(tools)
35+
self._tools = tools
4236

4337
def __setitem__(self, key, formula):
4438
self._cells[key] = formula
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import java.math.BigInteger;
2+
3+
class CorrectFactorial {
4+
static final BigInteger two = new BigInteger("2");
5+
6+
public static BigInteger factorial(BigInteger n) {
7+
return n.compareTo(two) < 0 ? BigInteger.ONE
8+
: n.multiply(factorial(n.subtract(BigInteger.ONE)));
9+
}
10+
11+
public static void main(String args[]) {
12+
BigInteger upperBound = new BigInteger("25");
13+
for (BigInteger i = BigInteger.ONE;
14+
i.compareTo(upperBound) <= 0;
15+
i = i.add(BigInteger.ONE)) {
16+
System.out.println(i + "! = " + factorial(i));
17+
}
18+
}
19+
}
20+
21+
/* output:
22+
23+
1! = 1
24+
2! = 2
25+
3! = 6
26+
4! = 24
27+
5! = 120
28+
6! = 720
29+
7! = 5040
30+
8! = 40320
31+
9! = 362880
32+
10! = 3628800
33+
11! = 39916800
34+
12! = 479001600
35+
13! = 6227020800
36+
14! = 87178291200
37+
15! = 1307674368000
38+
16! = 20922789888000
39+
17! = 355687428096000
40+
18! = 6402373705728000
41+
19! = 121645100408832000
42+
20! = 2432902008176640000
43+
21! = 51090942171709440000
44+
22! = 1124000727777607680000
45+
23! = 25852016738884976640000
46+
24! = 620448401733239439360000
47+
25! = 15511210043330985984000000
48+
49+
*/

0 commit comments

Comments
 (0)