Merge pull request #3 from eumiro/py36plus
Modernize code to Python 3.6+ and some cleanup
This commit is contained in:
commit
33f73a18a1
@ -26,7 +26,6 @@ Scalar multiplication::
|
||||
>>> abs(v * 3)
|
||||
15.0
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@ -39,7 +38,7 @@ class Vector:
|
||||
self.y = y
|
||||
|
||||
def __repr__(self):
|
||||
return 'Vector(%r, %r)' % (self.x, self.y)
|
||||
return f'Vector({self.x!r}, {self.y!r})'
|
||||
|
||||
def __abs__(self):
|
||||
return hypot(self.x, self.y)
|
||||
|
@ -11,11 +11,11 @@ Demonstration of ``bisect.bisect``::
|
||||
23 @ 11 | | | | | | | | | | |23
|
||||
22 @ 9 | | | | | | | | |22
|
||||
10 @ 5 | | | | |10
|
||||
8 @ 5 | | | | |8
|
||||
5 @ 3 | | |5
|
||||
2 @ 1 |2
|
||||
1 @ 1 |1
|
||||
0 @ 0 0
|
||||
8 @ 5 | | | | |8
|
||||
5 @ 3 | | |5
|
||||
2 @ 1 |2
|
||||
1 @ 1 |1
|
||||
0 @ 0 0
|
||||
|
||||
|
||||
Demonstration of ``bisect.bisect_left``::
|
||||
@ -27,11 +27,11 @@ Demonstration of ``bisect.bisect_left``::
|
||||
23 @ 9 | | | | | | | | |23
|
||||
22 @ 9 | | | | | | | | |22
|
||||
10 @ 5 | | | | |10
|
||||
8 @ 4 | | | |8
|
||||
5 @ 2 | |5
|
||||
2 @ 1 |2
|
||||
1 @ 0 1
|
||||
0 @ 0 0
|
||||
8 @ 4 | | | |8
|
||||
5 @ 2 | |5
|
||||
2 @ 1 |2
|
||||
1 @ 0 1
|
||||
0 @ 0 0
|
||||
|
||||
|
||||
"""
|
||||
@ -59,7 +59,7 @@ if __name__ == '__main__':
|
||||
bisect_fn = bisect.bisect
|
||||
|
||||
print('DEMO:', bisect_fn.__name__) # <5>
|
||||
print('haystack ->', ' '.join('%2d' % n for n in HAYSTACK))
|
||||
print('haystack ->', ' '.join(f'{n:2}' for n in HAYSTACK))
|
||||
demo(bisect_fn)
|
||||
|
||||
# END BISECT_DEMO
|
||||
|
@ -7,6 +7,6 @@ random.seed(1729)
|
||||
|
||||
my_list = []
|
||||
for i in range(SIZE):
|
||||
new_item = random.randrange(SIZE*2)
|
||||
new_item = random.randrange(SIZE * 2)
|
||||
bisect.insort(my_list, new_item)
|
||||
print('%2d ->' % new_item, my_list)
|
||||
print(f'{new_item:2} ->', my_list)
|
||||
|
@ -10,7 +10,7 @@ def non_ascii(c):
|
||||
|
||||
def clock(label, cmd):
|
||||
res = timeit.repeat(cmd, setup=SETUP, number=TIMES)
|
||||
print(label, *('{:.3f}'.format(x) for x in res))
|
||||
print(label, *(f'{x:.3f}' for x in res))
|
||||
|
||||
clock('listcomp :', '[ord(s) for s in symbols if ord(s) > 127]')
|
||||
clock('listcomp + func :', '[ord(s) for s in symbols if non_ascii(ord(s))]')
|
||||
|
@ -4,7 +4,7 @@ metro_lat_long.py
|
||||
Demonstration of nested tuple unpacking::
|
||||
|
||||
>>> main()
|
||||
| lat. | long.
|
||||
| lat. | long.
|
||||
Mexico City | 19.4333 | -99.1333
|
||||
New York-Newark | 40.8086 | -74.0204
|
||||
Sao Paulo | -23.5478 | -46.6358
|
||||
@ -20,11 +20,10 @@ metro_areas = [
|
||||
]
|
||||
|
||||
def main():
|
||||
print('{:15} | {:^9} | {:^9}'.format('', 'lat.', 'long.'))
|
||||
fmt = '{:15} | {:9.4f} | {:9.4f}'
|
||||
print(f'{"":15} | {"lat.":^9} | {"long.":^9}')
|
||||
for name, cc, pop, (latitude, longitude) in metro_areas: # <2>
|
||||
if longitude <= 0: # <3>
|
||||
print(fmt.format(name, latitude, longitude))
|
||||
print(f'{name:15} | {latitude:9.4f} | {longitude:9.4f}')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -16,7 +16,7 @@ with open(sys.argv[1], encoding='utf-8') as fp:
|
||||
for line_no, line in enumerate(fp, 1):
|
||||
for match in WORD_RE.finditer(line):
|
||||
word = match.group()
|
||||
column_no = match.start()+1
|
||||
column_no = match.start() + 1
|
||||
location = (line_no, column_no)
|
||||
index[word].append(location) # <2>
|
||||
|
||||
|
@ -41,15 +41,15 @@ def test(container_type, verbose):
|
||||
size=size, verbose=verbose)
|
||||
test = TEST.format(verbose=verbose)
|
||||
tt = timeit.repeat(stmt=test, setup=setup, repeat=5, number=1)
|
||||
print('|{:{}d}|{:f}'.format(size, MAX_EXPONENT + 1, min(tt)))
|
||||
print(f'|{size:{MAX_EXPONENT + 1}d}|{min(tt):f}')
|
||||
|
||||
if __name__=='__main__':
|
||||
if __name__ == '__main__':
|
||||
if '-v' in sys.argv:
|
||||
sys.argv.remove('-v')
|
||||
verbose = True
|
||||
else:
|
||||
verbose = False
|
||||
if len(sys.argv) != 2:
|
||||
print('Usage: %s <container_type>' % sys.argv[0])
|
||||
print(f'Usage: {sys.argv[0]} <container_type>')
|
||||
else:
|
||||
test(sys.argv[1], verbose)
|
||||
|
@ -2,8 +2,8 @@
|
||||
Generate data for container performance test
|
||||
"""
|
||||
|
||||
import random
|
||||
import array
|
||||
import random
|
||||
|
||||
MAX_EXPONENT = 7
|
||||
HAYSTACK_LEN = 10 ** MAX_EXPONENT
|
||||
@ -12,26 +12,26 @@ SAMPLE_LEN = HAYSTACK_LEN + NEEDLES_LEN // 2
|
||||
|
||||
needles = array.array('d')
|
||||
|
||||
sample = {1/random.random() for i in range(SAMPLE_LEN)}
|
||||
print('initial sample: %d elements' % len(sample))
|
||||
sample = {1 / random.random() for i in range(SAMPLE_LEN)}
|
||||
print(f'initial sample: {len(sample)} elements')
|
||||
|
||||
# complete sample, in case duplicate random numbers were discarded
|
||||
while len(sample) < SAMPLE_LEN:
|
||||
sample.add(1/random.random())
|
||||
sample.add(1 / random.random())
|
||||
|
||||
print('complete sample: %d elements' % len(sample))
|
||||
print(f'complete sample: {len(sample)} elements')
|
||||
|
||||
sample = array.array('d', sample)
|
||||
random.shuffle(sample)
|
||||
|
||||
not_selected = sample[:NEEDLES_LEN // 2]
|
||||
print('not selected: %d samples' % len(not_selected))
|
||||
print(f'not selected: {len(not_selected)} samples')
|
||||
print(' writing not_selected.arr')
|
||||
with open('not_selected.arr', 'wb') as fp:
|
||||
not_selected.tofile(fp)
|
||||
|
||||
selected = sample[NEEDLES_LEN // 2:]
|
||||
print('selected: %d samples' % len(selected))
|
||||
print(f'selected: {len(selected)} samples')
|
||||
print(' writing selected.arr')
|
||||
with open('selected.arr', 'wb') as fp:
|
||||
selected.tofile(fp)
|
||||
|
@ -1,17 +1,17 @@
|
||||
import sys
|
||||
|
||||
MAX_BITS = len(format(sys.maxsize, 'b'))
|
||||
print('%s-bit Python build' % (MAX_BITS + 1))
|
||||
print(f'{MAX_BITS + 1}-bit Python build')
|
||||
|
||||
def hash_diff(o1, o2):
|
||||
h1 = '{:>0{}b}'.format(hash(o1), MAX_BITS)
|
||||
h2 = '{:>0{}b}'.format(hash(o2), MAX_BITS)
|
||||
h1 = f'{hash(o1):>0{MAX_BITS}b}'
|
||||
h2 = f'{hash(o2):>0{MAX_BITS}b}'
|
||||
diff = ''.join('!' if b1 != b2 else ' ' for b1, b2 in zip(h1, h2))
|
||||
count = '!= {}'.format(diff.count('!'))
|
||||
count = f'!= {diff.count("!")}'
|
||||
width = max(len(repr(o1)), len(repr(o2)), 8)
|
||||
sep = '-' * (width * 2 + MAX_BITS)
|
||||
return '{!r:{width}} {}\n{:{width}} {} {}\n{!r:{width}} {}\n{}'.format(
|
||||
o1, h1, ' ' * width, diff, count, o2, h2, sep, width=width)
|
||||
return (f'{o1!r:{width}} {h1}\n{" ":{width}} {diff} {count}\n'
|
||||
f'{o2!r:{width}} {h2}\n{sep}')
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(hash_diff(1, 1.0))
|
||||
|
@ -17,7 +17,7 @@ _sentinel = object()
|
||||
|
||||
|
||||
class TransformDict(MutableMapping):
|
||||
'''Dictionary that calls a transformation function when looking
|
||||
"""Dictionary that calls a transformation function when looking
|
||||
up keys, but preserves the original keys.
|
||||
|
||||
>>> d = TransformDict(str.lower)
|
||||
@ -26,18 +26,18 @@ class TransformDict(MutableMapping):
|
||||
True
|
||||
>>> set(d.keys())
|
||||
{'Foo'}
|
||||
'''
|
||||
"""
|
||||
|
||||
__slots__ = ('_transform', '_original', '_data')
|
||||
|
||||
def __init__(self, transform, init_dict=None, **kwargs):
|
||||
'''Create a new TransformDict with the given *transform* function.
|
||||
"""Create a new TransformDict with the given *transform* function.
|
||||
*init_dict* and *kwargs* are optional initializers, as in the
|
||||
dict constructor.
|
||||
'''
|
||||
"""
|
||||
if not callable(transform):
|
||||
msg = 'expected a callable, got %r'
|
||||
raise TypeError(msg % transform.__class__)
|
||||
raise TypeError(
|
||||
f'expected a callable, got {transform.__class__!r}')
|
||||
self._transform = transform
|
||||
# transformed => original
|
||||
self._original = {}
|
||||
@ -48,7 +48,7 @@ class TransformDict(MutableMapping):
|
||||
self.update(kwargs)
|
||||
|
||||
def getitem(self, key):
|
||||
'D.getitem(key) -> (stored key, value)'
|
||||
"""D.getitem(key) -> (stored key, value)"""
|
||||
transformed = self._transform(key)
|
||||
original = self._original[transformed]
|
||||
value = self._data[transformed]
|
||||
@ -56,7 +56,7 @@ class TransformDict(MutableMapping):
|
||||
|
||||
@property
|
||||
def transform_func(self):
|
||||
"This TransformDict's transformation function"
|
||||
"""This TransformDict's transformation function"""
|
||||
return self._transform
|
||||
|
||||
# Minimum set of methods required for MutableMapping
|
||||
@ -83,7 +83,7 @@ class TransformDict(MutableMapping):
|
||||
# Methods overridden to mitigate the performance overhead.
|
||||
|
||||
def clear(self):
|
||||
'D.clear() -> None. Remove all items from D.'
|
||||
"""D.clear() -> None. Remove all items from D."""
|
||||
self._data.clear()
|
||||
self._original.clear()
|
||||
|
||||
@ -91,14 +91,14 @@ class TransformDict(MutableMapping):
|
||||
return self._transform(key) in self._data
|
||||
|
||||
def get(self, key, default=None):
|
||||
'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.'
|
||||
"""D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None."""
|
||||
return self._data.get(self._transform(key), default)
|
||||
|
||||
def pop(self, key, default=_sentinel):
|
||||
'''D.pop(k[,d]) -> v, remove key and return corresponding value.
|
||||
"""D.pop(k[,d]) -> v, remove key and return corresponding value.
|
||||
If key is not found, d is returned if given, otherwise
|
||||
KeyError is raised.
|
||||
'''
|
||||
"""
|
||||
transformed = self._transform(key)
|
||||
if default is _sentinel:
|
||||
del self._original[transformed]
|
||||
@ -108,16 +108,16 @@ class TransformDict(MutableMapping):
|
||||
return self._data.pop(transformed, default)
|
||||
|
||||
def popitem(self):
|
||||
'''D.popitem() -> (k, v), remove and return some (key, value) pair
|
||||
"""D.popitem() -> (k, v), remove and return some (key, value) pair
|
||||
as a 2-tuple; but raise KeyError if D is empty.
|
||||
'''
|
||||
"""
|
||||
transformed, value = self._data.popitem()
|
||||
return self._original.pop(transformed), value
|
||||
|
||||
# Other methods
|
||||
|
||||
def copy(self):
|
||||
'D.copy() -> a shallow copy of D'
|
||||
"""D.copy() -> a shallow copy of D"""
|
||||
other = self.__class__(self._transform)
|
||||
other._original = self._original.copy()
|
||||
other._data = self._data.copy()
|
||||
@ -137,5 +137,4 @@ class TransformDict(MutableMapping):
|
||||
except TypeError:
|
||||
# Some keys are unhashable, fall back on .items()
|
||||
equiv = list(self.items())
|
||||
return '%s(%r, %s)' % (self.__class__.__name__,
|
||||
self._transform, repr(equiv))
|
||||
return f'{self.__class__.__name__}({self._transform!r}, {equiv!r})'
|
||||
|
@ -8,7 +8,7 @@ FIRST, LAST = ord(' '), sys.maxunicode # <1>
|
||||
def find(*query_words, first=FIRST, last=LAST): # <2>
|
||||
query = {w.upper() for w in query_words} # <3>
|
||||
count = 0
|
||||
for code in range(first, last + 1):
|
||||
for code in range(first, last + 1):
|
||||
char = chr(code) # <4>
|
||||
name = unicodedata.name(char, None) # <5>
|
||||
if name and query.issubset(name.split()): # <6>
|
||||
|
@ -18,4 +18,4 @@ my_file = open('dummy', 'w')
|
||||
|
||||
for expression in expressions.split():
|
||||
value = eval(expression)
|
||||
print(expression.rjust(30), '->', repr(value))
|
||||
print(f'{expression:>30} -> {value!r}')
|
||||
|
@ -7,12 +7,12 @@ re_digit = re.compile(r'\d')
|
||||
sample = '1\xbc\xb2\u0969\u136b\u216b\u2466\u2480\u3285'
|
||||
|
||||
for char in sample:
|
||||
print('U+%04x' % ord(char), # <1>
|
||||
print(f'U+{ord(char):04x}', # <1>
|
||||
char.center(6), # <2>
|
||||
're_dig' if re_digit.match(char) else '-', # <3>
|
||||
'isdig' if char.isdigit() else '-', # <4>
|
||||
'isnum' if char.isnumeric() else '-', # <5>
|
||||
format(unicodedata.numeric(char), '5.2f'), # <6>
|
||||
f'{unicodedata.numeric(char):5.2f}', # <6>
|
||||
unicodedata.name(char), # <7>
|
||||
sep='\t')
|
||||
# end::NUMERICS_DEMO[]
|
||||
|
@ -11,7 +11,7 @@ text_str = ("Ramanujan saw \u0be7\u0bed\u0be8\u0bef" # <3>
|
||||
|
||||
text_bytes = text_str.encode('utf_8') # <5>
|
||||
|
||||
print('Text', repr(text_str), sep='\n ')
|
||||
print(f'Text\n {text_str!r}')
|
||||
print('Numbers')
|
||||
print(' str :', re_numbers_str.findall(text_str)) # <6>
|
||||
print(' bytes:', re_numbers_bytes.findall(text_bytes)) # <7>
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
"""
|
||||
Radical folding and text sanitizing.
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Coordinate:
|
||||
|
||||
lat: float
|
||||
long: float
|
||||
|
||||
|
||||
def __str__(self):
|
||||
ns = 'N' if self.lat >= 0 else 'S'
|
||||
we = 'E' if self.long >= 0 else 'W'
|
||||
|
@ -30,7 +30,7 @@ To fix, ``leo2`` must be created with an explicit ``handle``::
|
||||
|
||||
# tag::HACKERCLUB[]
|
||||
from dataclasses import dataclass
|
||||
from club import ClubMember
|
||||
from club import ClubMember
|
||||
|
||||
@dataclass
|
||||
class HackerClubMember(ClubMember): # <1>
|
||||
|
@ -31,7 +31,7 @@ To fix, ``leo2`` must be created with an explicit ``handle``::
|
||||
# tag::HACKERCLUB[]
|
||||
from dataclasses import dataclass
|
||||
from typing import ClassVar, Set
|
||||
from club import ClubMember
|
||||
from club import ClubMember
|
||||
|
||||
@dataclass
|
||||
class HackerClubMember(ClubMember):
|
||||
|
@ -14,7 +14,7 @@ A complete resource record:
|
||||
>>> description = 'Improving the design of existing code'
|
||||
>>> book = Resource('978-0-13-475759-9', 'Refactoring, 2nd Edition',
|
||||
... ['Martin Fowler', 'Kent Beck'], date(2018, 11, 19),
|
||||
... ResourceType.BOOK, description, 'EN',
|
||||
... ResourceType.BOOK, description, 'EN',
|
||||
... ['computer programming', 'OOP'])
|
||||
>>> book # doctest: +NORMALIZE_WHITESPACE
|
||||
Resource(identifier='978-0-13-475759-9', title='Refactoring, 2nd Edition',
|
||||
|
@ -21,7 +21,7 @@ A complete resource record:
|
||||
>>> description = 'Improving the design of existing code'
|
||||
>>> book = Resource('978-0-13-475759-9', 'Refactoring, 2nd Edition',
|
||||
... ['Martin Fowler', 'Kent Beck'], date(2018, 11, 19),
|
||||
... ResourceType.BOOK, description, 'EN',
|
||||
... ResourceType.BOOK, description, 'EN',
|
||||
... ['computer programming', 'OOP'])
|
||||
|
||||
# tag::DOCTEST[]
|
||||
|
@ -14,7 +14,7 @@ class Coordinate(NamedTuple):
|
||||
|
||||
lat: float
|
||||
long: float
|
||||
|
||||
|
||||
def __str__(self):
|
||||
ns = 'N' if self.lat >= 0 else 'S'
|
||||
we = 'E' if self.long >= 0 else 'W'
|
||||
|
@ -6,4 +6,4 @@ class Coordinate(typing.NamedTuple):
|
||||
long: float
|
||||
|
||||
trash = Coordinate('foo', None) # <1>
|
||||
print(trash)
|
||||
print(trash)
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
"""
|
||||
>>> import copy
|
||||
>>> bus1 = Bus(['Alice', 'Bill', 'Claire', 'David'])
|
||||
|
@ -2,7 +2,7 @@
|
||||
>>> import weakref
|
||||
>>> stock = weakref.WeakValueDictionary()
|
||||
>>> catalog = [Cheese('Red Leicester'), Cheese('Tilsit'),
|
||||
... Cheese('Brie'), Cheese('Parmesan')]
|
||||
... Cheese('Brie'), Cheese('Parmesan')]
|
||||
...
|
||||
>>> for cheese in catalog:
|
||||
... stock[cheese.kind] = cheese
|
||||
@ -24,5 +24,5 @@ class Cheese:
|
||||
self.kind = kind
|
||||
|
||||
def __repr__(self):
|
||||
return 'Cheese(%r)' % self.kind
|
||||
return f'Cheese({self.kind!r})'
|
||||
# end::CHEESE_CLASS[]
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
"""
|
||||
# tag::TAG_DEMO[]
|
||||
>>> tag('br') # <1>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
import sys
|
||||
from array import array
|
||||
from typing import Mapping, MutableSequence, Callable, Iterable, Sequence, Union, Any
|
||||
from typing import Mapping, MutableSequence, Callable, Iterable, Union, Any
|
||||
|
||||
|
||||
OPERATORS: Mapping[str, Callable[[float, float], float]] = {
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
"""
|
||||
>>> import copy
|
||||
>>> bus1 = Bus(['Alice', 'Bill', 'Claire', 'David'])
|
||||
|
@ -17,7 +17,7 @@ import re
|
||||
import unicodedata
|
||||
from typing import Dict, Set, Iterator
|
||||
|
||||
RE_WORD = re.compile('\w+')
|
||||
RE_WORD = re.compile(r'\w+')
|
||||
STOP_CODE = sys.maxunicode + 1
|
||||
|
||||
def tokenize(text: str) -> Iterator[str]: # <1>
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
# tag::CLIP_ANNOT[]
|
||||
|
||||
def clip(text:str, max_len:'int > 0'=80) -> str: # <1>
|
||||
def clip(text: str, max_len: 'int > 0'=80) -> str: # <1>
|
||||
"""Return text clipped at the last space before or after max_len
|
||||
"""
|
||||
end = None
|
||||
|
@ -21,7 +21,7 @@ NAMES = {
|
||||
|
||||
def rgb2hex(color=Tuple[int, int, int]) -> str:
|
||||
if any(c not in range(256) for c in color):
|
||||
raise ValueError('Color components must be in range(256)')
|
||||
raise ValueError('Color components must be in range(256)')
|
||||
values = (f'{n % 256:02x}' for n in color)
|
||||
return '#' + ''.join(values)
|
||||
|
||||
|
@ -31,7 +31,7 @@ def demo() -> None:
|
||||
print(f'{cell:5}', end='')
|
||||
print()
|
||||
print()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
demo()
|
||||
|
@ -48,7 +48,7 @@ def test_columnize_8_in_3():
|
||||
|
||||
def test_columnize_8_in_5():
|
||||
# Not the right number of columns, but the right number of rows.
|
||||
# This acually looks better, so it's OK!
|
||||
# This actually looks better, so it's OK!
|
||||
sequence = 'ABCDEFGH'
|
||||
expected = [
|
||||
('A', 'C', 'E', 'G'),
|
||||
@ -60,7 +60,7 @@ def test_columnize_8_in_5():
|
||||
|
||||
def test_columnize_7_in_5():
|
||||
# Not the right number of columns, but the right number of rows.
|
||||
# This acually looks better, so it's OK!
|
||||
# This actually looks better, so it's OK!
|
||||
sequence = 'ABCDEFG'
|
||||
expected = [
|
||||
('A', 'C', 'E', 'G'),
|
||||
|
@ -24,7 +24,7 @@ def max(__iterable: Iterable[_CT], *, key: None = ...) -> _CT:
|
||||
def max(__iterable: Iterable[_T], *, key: Callable[[_T], _CT]) -> _T:
|
||||
...
|
||||
@overload
|
||||
def max(__iterable: Iterable[_CT], *, key: None = ...,
|
||||
def max(__iterable: Iterable[_CT], *, key: None = ...,
|
||||
default: _DT) -> Union[_CT, _DT]:
|
||||
...
|
||||
@overload
|
||||
|
@ -8,7 +8,7 @@ Example:
|
||||
>>> l = 'mango pear apple kiwi banana'.split()
|
||||
>>> top(l, 3)
|
||||
['pear', 'mango', 'kiwi']
|
||||
>>>
|
||||
>>>
|
||||
>>> l2 = [(len(s), s) for s in l]
|
||||
>>> l2
|
||||
[(5, 'mango'), (4, 'pear'), (5, 'apple'), (4, 'kiwi'), (6, 'banana')]
|
||||
|
@ -14,6 +14,6 @@ from geolib import geohash as gh # type: ignore
|
||||
|
||||
PRECISION = 9
|
||||
|
||||
def geohash(lat_lon = Tuple[float, float]) -> str:
|
||||
def geohash(lat_lon: Tuple[float, float]) -> str:
|
||||
return gh.encode(*lat_lon, PRECISION)
|
||||
# end::GEOHASH[]
|
@ -13,7 +13,7 @@ def mode(data: Iterable[T]) -> T:
|
||||
|
||||
def demo() -> None:
|
||||
from typing import List, Set, TYPE_CHECKING
|
||||
pop:List[Set] = [set(), set()]
|
||||
pop: List[Set] = [set(), set()]
|
||||
m = mode(pop)
|
||||
if TYPE_CHECKING:
|
||||
reveal_type(pop)
|
||||
|
@ -13,7 +13,7 @@ def mode(data: Iterable[NumberT]) -> NumberT:
|
||||
|
||||
|
||||
def demo() -> None:
|
||||
from typing import List, Set, TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING
|
||||
pop = [Fraction(1, 2), Fraction(1, 3), Fraction(1, 4), Fraction(1, 2)]
|
||||
m = mode(pop)
|
||||
if TYPE_CHECKING:
|
||||
|
@ -57,7 +57,7 @@ def load_hash() -> Tuple[bytes, bytes]:
|
||||
sys.exit(2)
|
||||
|
||||
salt, stored_hash = salted_hash.split(b':')
|
||||
return (b64decode(salt), b64decode(stored_hash))
|
||||
return b64decode(salt), b64decode(stored_hash)
|
||||
|
||||
|
||||
def practice() -> None:
|
||||
@ -83,8 +83,7 @@ def practice() -> None:
|
||||
print(f' {answer}\thits={correct}\tmisses={turn-correct}')
|
||||
|
||||
if turn:
|
||||
pct = correct / turn * 100
|
||||
print(f'\n{turn} turns. {pct:0.1f}% correct.')
|
||||
print(f'\n{turn} turns. {correct / turn:.1%} correct.')
|
||||
|
||||
|
||||
def main(argv: Sequence[str]) -> None:
|
||||
|
@ -30,7 +30,7 @@ def demo() -> None:
|
||||
l33t = [(p[0], p[1]) for p in 'a4 e3 i1 o0'.split()]
|
||||
text = 'mad skilled noob powned leet'
|
||||
print(zip_replace(text, l33t))
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
demo()
|
||||
|
@ -33,7 +33,7 @@ def demo() -> None:
|
||||
l33t = [FromTo(*p) for p in 'a4 e3 i1 o0'.split()]
|
||||
text = 'mad skilled noob powned leet'
|
||||
print(zip_replace(text, l33t))
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
demo()
|
||||
|
@ -17,7 +17,7 @@ def to_xml(book: BookDict) -> str: # <1>
|
||||
for key, value in book.items():
|
||||
if isinstance(value, list): # <3>
|
||||
elements.extend(AUTHOR_EL.format(n)
|
||||
for n in value)
|
||||
for n in value)
|
||||
else:
|
||||
tag = key.upper()
|
||||
elements.append(f'<{tag}>{value}</{tag}>')
|
||||
|
@ -1,6 +1,3 @@
|
||||
import json
|
||||
from typing import cast
|
||||
|
||||
from books import BookDict, to_xml
|
||||
|
||||
XML_SAMPLE = """
|
||||
|
@ -28,6 +28,6 @@ def make_averager():
|
||||
def averager(new_value):
|
||||
series.append(new_value)
|
||||
total = sum(series)
|
||||
return total/len(series)
|
||||
return total / len(series)
|
||||
|
||||
return averager
|
||||
|
@ -10,7 +10,7 @@
|
||||
"""
|
||||
|
||||
|
||||
class Averager():
|
||||
class Averager:
|
||||
|
||||
def __init__(self):
|
||||
self.series = []
|
||||
|
@ -5,7 +5,7 @@ from clockdeco import clock
|
||||
def fibonacci(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fibonacci(n-2) + fibonacci(n-1)
|
||||
return fibonacci(n - 2) + fibonacci(n - 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -8,7 +8,7 @@ from clockdeco import clock
|
||||
def fibonacci(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fibonacci(n-2) + fibonacci(n-1)
|
||||
return fibonacci(n - 2) + fibonacci(n - 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -8,7 +8,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5), # <2>
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, FidelityPromo()) # <3>
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, FidelityPromo()) # <4>
|
||||
@ -72,8 +72,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
class Promotion(ABC): # the Strategy: an abstract base class
|
||||
|
@ -21,7 +21,7 @@ def cart_plain() -> List[LineItem]:
|
||||
return [
|
||||
LineItem('banana', 4, 0.5),
|
||||
LineItem('apple', 10, 1.5),
|
||||
LineItem('watermellon', 5, 5.0),
|
||||
LineItem('watermelon', 5, 5.0),
|
||||
]
|
||||
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5), # <2>
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, FidelityPromo()) # <3>
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, FidelityPromo()) # <4>
|
||||
@ -29,7 +29,6 @@
|
||||
# tag::CLASSIC_STRATEGY[]
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from collections import namedtuple
|
||||
import typing
|
||||
|
||||
|
||||
@ -69,8 +68,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
class Promotion(ABC): # the Strategy: an abstract base class
|
||||
|
@ -20,7 +20,7 @@ def customer_fidelity_1100() -> Customer:
|
||||
def cart_plain() -> List[LineItem]:
|
||||
return [LineItem('banana', 4, .5),
|
||||
LineItem('apple', 10, 1.5),
|
||||
LineItem('watermellon', 5, 5.0)]
|
||||
LineItem('watermelon', 5, 5.0)]
|
||||
|
||||
|
||||
def test_fidelity_promo_no_discount(customer_fidelity_0, cart_plain) -> None:
|
||||
|
@ -8,7 +8,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5), # <2>
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, FidelityPromo()) # <3>
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, FidelityPromo()) # <4>
|
||||
@ -29,7 +29,6 @@
|
||||
# tag::CLASSIC_STRATEGY[]
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from collections import namedtuple
|
||||
import typing
|
||||
|
||||
from pytypes import typelogged
|
||||
@ -71,8 +70,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
@typelogged
|
||||
|
@ -20,7 +20,7 @@ def customer_fidelity_1100() -> Customer:
|
||||
def cart_plain() -> List[LineItem]:
|
||||
return [LineItem('banana', 4, .5),
|
||||
LineItem('apple', 10, 1.5),
|
||||
LineItem('watermellon', 5, 5.0)]
|
||||
LineItem('watermelon', 5, 5.0)]
|
||||
|
||||
|
||||
def test_fidelity_promo_no_discount(customer_fidelity_0, cart_plain) -> None:
|
||||
|
@ -8,7 +8,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity_promo) # <2>
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity_promo)
|
||||
@ -71,8 +71,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
# <2>
|
||||
|
@ -7,7 +7,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> banana_cart = [LineItem('banana', 30, .5),
|
||||
... LineItem('apple', 10, 1.5)]
|
||||
>>> big_cart = [LineItem(str(item_code), 1, 1.0)
|
||||
|
@ -7,7 +7,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity_promo)
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity_promo)
|
||||
@ -69,8 +69,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
def fidelity_promo(order):
|
||||
|
@ -8,7 +8,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity_promo)
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity_promo)
|
||||
@ -73,8 +73,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
# tag::STRATEGY_BEST3[]
|
||||
|
@ -8,7 +8,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity)
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity)
|
||||
@ -71,8 +71,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
# tag::STRATEGY_BEST4[]
|
||||
|
@ -6,7 +6,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity_promo(10))
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity_promo(10))
|
||||
@ -73,8 +73,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
# tag::STRATEGY_PARAM[]
|
||||
@ -85,7 +84,7 @@ Promotion = Callable[[Order], float] # <2>
|
||||
def fidelity_promo(percent: float) -> Promotion:
|
||||
"""discount for customers with 1000 or more fidelity points"""
|
||||
return lambda order: (
|
||||
order.total() * percent / 100.0 if order.customer.fidelity >= 1000 else 0
|
||||
order.total() * percent / 100 if order.customer.fidelity >= 1000 else 0
|
||||
)
|
||||
|
||||
|
||||
@ -96,7 +95,7 @@ def bulk_item_promo(percent: float) -> Promotion:
|
||||
discount = 0
|
||||
for item in order.cart:
|
||||
if item.quantity >= 20:
|
||||
discount += item.total() * percent / 100.0
|
||||
discount += item.total() * percent / 100
|
||||
return discount
|
||||
|
||||
return discounter
|
||||
@ -111,13 +110,13 @@ class LargeOrderPromo:
|
||||
def __call__(self, order: Order) -> float:
|
||||
distinct_items = {item.product for item in order.cart}
|
||||
if len(distinct_items) >= 10:
|
||||
return order.total() * self.percent / 100.0
|
||||
return order.total() * self.percent / 100
|
||||
return 0
|
||||
|
||||
|
||||
def general_discount(percent: float, order: Order) -> float:
|
||||
"""unrestricted discount; usage: ``partial(general_discount, 5)``"""
|
||||
return order.total() * percent / 100.0
|
||||
return order.total() * percent / 100
|
||||
|
||||
|
||||
# end::STRATEGY[]
|
||||
|
@ -23,7 +23,7 @@ def cart_plain() -> List[LineItem]:
|
||||
return [
|
||||
LineItem('banana', 4, 0.5),
|
||||
LineItem('apple', 10, 1.5),
|
||||
LineItem('watermellon', 5, 5.0),
|
||||
LineItem('watermelon', 5, 5.0),
|
||||
]
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@ def cart_plain() -> List[LineItem]:
|
||||
return [
|
||||
LineItem('banana', 4, 0.5),
|
||||
LineItem('apple', 10, 1.5),
|
||||
LineItem('watermellon', 5, 5.0),
|
||||
LineItem('watermelon', 5, 5.0),
|
||||
]
|
||||
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5), # <2>
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, FidelityPromo()) # <3>
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, FidelityPromo()) # <4>
|
||||
@ -65,8 +65,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
class Promotion(ABC): # the Strategy: an abstract base class
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
def fidelity_promo(order):
|
||||
"""5% discount for customers with 1000 or more fidelity points"""
|
||||
return order.total() * .05 if order.customer.fidelity >= 1000 else 0
|
||||
|
@ -8,7 +8,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity_promo) # <2>
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity_promo)
|
||||
@ -64,8 +64,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
# <2>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity_promo)
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity_promo)
|
||||
@ -71,8 +71,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
def fidelity_promo(order):
|
||||
|
@ -7,7 +7,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity_promo)
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity_promo)
|
||||
@ -71,8 +71,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
def fidelity_promo(order):
|
||||
|
@ -8,7 +8,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity_promo)
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity_promo)
|
||||
@ -75,8 +75,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
# tag::STRATEGY_BEST3[]
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity)
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity)
|
||||
@ -72,8 +72,7 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
# tag::STRATEGY_BEST4[]
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity_promo(10))
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity_promo(10))
|
||||
@ -60,13 +60,12 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
def fidelity_promo(percent):
|
||||
"""discount for customers with 1000 or more fidelity points"""
|
||||
return lambda order: (order.total() * percent/100.0
|
||||
return lambda order: (order.total() * percent / 100
|
||||
if order.customer.fidelity >= 1000 else 0)
|
||||
|
||||
|
||||
@ -76,7 +75,7 @@ def bulk_item_promo(percent):
|
||||
discount = 0
|
||||
for item in order.cart:
|
||||
if item.quantity >= 20:
|
||||
discount += item.total() * percent/100.0
|
||||
discount += item.total() * percent / 100
|
||||
return discount
|
||||
return discounter
|
||||
|
||||
@ -86,6 +85,6 @@ def large_order_promo(percent):
|
||||
def discounter(order):
|
||||
distinct_items = {item.product for item in order.cart}
|
||||
if len(distinct_items) >= 10:
|
||||
return order.total() * percent / 100.0
|
||||
return order.total() * percent / 100
|
||||
return 0
|
||||
return discounter
|
||||
|
@ -6,7 +6,7 @@
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
... LineItem('watermelon', 5, 5.0)]
|
||||
>>> Order(joe, cart, FidelityPromo(10))
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, FidelityPromo(10))
|
||||
@ -60,11 +60,10 @@ class Order: # the Context
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
|
||||
|
||||
|
||||
class Promotion():
|
||||
class Promotion:
|
||||
"""compute discount for order"""
|
||||
|
||||
def __init__(self, percent):
|
||||
@ -79,7 +78,7 @@ class FidelityPromo(Promotion):
|
||||
|
||||
def __call__(self, order):
|
||||
if order.customer.fidelity >= 1000:
|
||||
return order.total() * self.percent/100.0
|
||||
return order.total() * self.percent / 100
|
||||
return 0
|
||||
|
||||
|
||||
@ -90,7 +89,7 @@ class BulkItemPromo(Promotion):
|
||||
discount = 0
|
||||
for item in order.cart:
|
||||
if item.quantity >= 20:
|
||||
discount += item.total() * self.percent/100.0
|
||||
discount += item.total() * self.percent / 100
|
||||
return discount
|
||||
|
||||
|
||||
@ -100,5 +99,5 @@ class LargeOrderPromo(Promotion):
|
||||
def __call__(self, order):
|
||||
distinct_items = {item.product for item in order.cart}
|
||||
if len(distinct_items) >= 10:
|
||||
return order.total() * self.percent / 100.0
|
||||
return order.total() * self.percent / 100
|
||||
return 0
|
||||
|
@ -8,17 +8,17 @@ if len(sys.argv) == 2:
|
||||
module_name = sys.argv[1].replace('.py', '')
|
||||
module = importlib.import_module(module_name)
|
||||
else:
|
||||
print('Usage: {} <vector-module-to-test>'.format())
|
||||
print(f'Usage: {sys.argv[0]} <vector-module-to-test>')
|
||||
sys.exit(1)
|
||||
|
||||
fmt = 'Selected Vector2d type: {.__name__}.{.__name__}'
|
||||
print(fmt.format(module, module.Vector2d))
|
||||
|
||||
mem_init = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
|
||||
print('Creating {:,} Vector2d instances'.format(NUM_VECTORS))
|
||||
print(f'Creating {NUM_VECTORS:,} Vector2d instances')
|
||||
|
||||
vectors = [module.Vector2d(3.0, 4.0) for i in range(NUM_VECTORS)]
|
||||
|
||||
mem_final = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
|
||||
print('Initial RAM usage: {:14,}'.format(mem_init))
|
||||
print(' Final RAM usage: {:14,}'.format(mem_final))
|
||||
print(f'Initial RAM usage: {mem_init:14,}')
|
||||
print(f' Final RAM usage: {mem_final:14,}')
|
||||
|
@ -18,7 +18,7 @@ public class Expose {
|
||||
System.out.println("message.secret = " + wasHidden);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
// this will not happen after setAcessible(true)
|
||||
// this will not happen after setAccessible(true)
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,4 @@ import Confidential
|
||||
message = Confidential('top secret text')
|
||||
secret_field = Confidential.getDeclaredField('secret')
|
||||
secret_field.setAccessible(True) # break the lock!
|
||||
print 'message.secret =', secret_field.get(message)
|
||||
print('message.secret =', secret_field.get(message))
|
||||
|
@ -7,5 +7,5 @@ for field in fields:
|
||||
# list private fields only
|
||||
if Modifier.isPrivate(field.getModifiers()):
|
||||
field.setAccessible(True) # break the lock
|
||||
print 'field:', field
|
||||
print '\t', field.getName(), '=', field.get(message)
|
||||
print('field:', field)
|
||||
print('\t', field.getName(), '=', field.get(message))
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
"""
|
||||
In the Jython registry file there is this line:
|
||||
|
||||
@ -14,4 +13,4 @@ message = Confidential('top secret text')
|
||||
for name in dir(message):
|
||||
attr = getattr(message, name)
|
||||
if not callable(attr): # non-methods only
|
||||
print name + '\t=', attr
|
||||
print(name + '\t=', attr)
|
||||
|
@ -81,7 +81,7 @@ Tests of hashing:
|
||||
>>> v2 = Vector2d(3.1, 4.2)
|
||||
>>> hash(v1), hash(v2)
|
||||
(7, 384307168202284039)
|
||||
>>> len(set([v1, v2]))
|
||||
>>> len({v1, v2})
|
||||
2
|
||||
|
||||
"""
|
||||
|
@ -83,7 +83,7 @@ Tests of hashing:
|
||||
>>> v2 = Vector2d(3.1, 4.2)
|
||||
>>> hash(v1), hash(v2)
|
||||
(7, 384307168202284039)
|
||||
>>> len(set([v1, v2]))
|
||||
>>> len({v1, v2})
|
||||
2
|
||||
|
||||
# end::VECTOR2D_V3_DEMO[]
|
||||
|
@ -80,7 +80,7 @@ Tests of hashing:
|
||||
>>> v2 = Vector2d(3.1, 4.2)
|
||||
>>> hash(v1), hash(v2)
|
||||
(7, 384307168202284039)
|
||||
>>> len(set([v1, v2]))
|
||||
>>> len({v1, v2})
|
||||
2
|
||||
|
||||
# end::VECTOR2D_V3_DEMO[]
|
||||
|
@ -1,5 +1,4 @@
|
||||
import math
|
||||
import itertools
|
||||
|
||||
|
||||
PRIME_FIXTURE = [
|
||||
@ -36,7 +35,7 @@ def is_prime(n) -> bool:
|
||||
if n % 2 == 0:
|
||||
return False
|
||||
|
||||
root = int(math.floor(math.sqrt(n)))
|
||||
root = math.floor(math.sqrt(n))
|
||||
for i in range(3, root + 1, 2):
|
||||
if n % i == 0:
|
||||
return False
|
||||
|
@ -34,10 +34,10 @@ def main() -> None:
|
||||
label = 'P' if prime else ' '
|
||||
print(f'{n:16} {label} {elapsed:9.6f}s')
|
||||
|
||||
|
||||
time = perf_counter() - t0
|
||||
print('Total time:', f'{time:0.2f}s')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
# end::PRIMES_PROC_MAIN[]
|
||||
|
@ -18,7 +18,7 @@ async def is_prime(n):
|
||||
return False
|
||||
|
||||
sleep = asyncio.sleep # <1>
|
||||
root = int(math.floor(math.sqrt(n)))
|
||||
root = math.floor(math.sqrt(n))
|
||||
for i in range(3, root + 1, 2):
|
||||
if n % i == 0:
|
||||
return False
|
||||
|
@ -18,7 +18,7 @@ async def is_prime(n):
|
||||
return False
|
||||
|
||||
sleep = asyncio.sleep # <1>
|
||||
root = int(math.floor(math.sqrt(n)))
|
||||
root = math.floor(math.sqrt(n))
|
||||
for i in range(3, root + 1, 2):
|
||||
if n % i == 0:
|
||||
return False
|
||||
|
@ -7,7 +7,6 @@
|
||||
from multiprocessing import Process, Event
|
||||
from multiprocessing import synchronize
|
||||
import itertools
|
||||
import time
|
||||
|
||||
from primes import is_prime
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
from threading import Thread, Event
|
||||
import itertools
|
||||
import time
|
||||
|
||||
from primes import is_prime
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
# tag::SPINNER_THREAD_TOP[]
|
||||
from threading import Thread, Event
|
||||
import itertools
|
||||
import time
|
||||
|
||||
from primes import is_prime
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
from time import perf_counter
|
||||
from typing import Tuple, List, NamedTuple
|
||||
from typing import List, NamedTuple
|
||||
from threading import Thread
|
||||
from queue import SimpleQueue
|
||||
|
||||
|
@ -49,4 +49,4 @@ Part / Chapter #|Title|Directory|Notebook|1<sup>st</sup> ed. Chapter #
|
||||
**VI – Metaprogramming**|
|
||||
22|Dynamic Attributes and Properties|[22-dyn-attr-prop](22-dyn-attr-prop)||19
|
||||
23|Attribute Descriptors|[23-descriptor](23-descriptor)||20
|
||||
24|Class Metapgrogramming|[24-class-metaprog](24-class-metaprog)||21
|
||||
24|Class Metaprogramming|[24-class-metaprog](24-class-metaprog)||21
|
||||
|
Loading…
Reference in New Issue
Block a user