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
0 commit comments