updated from Atlas
This commit is contained in:
20
attic/sequences/bisect_demo_pos.py
Normal file
20
attic/sequences/bisect_demo_pos.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import random
|
||||
import collections
|
||||
|
||||
SIZE = 15
|
||||
|
||||
random.seed(1729)
|
||||
|
||||
target_list = [random.randrange(SIZE*2) for i in range(SIZE)]
|
||||
target_list.sort()
|
||||
|
||||
random.seed(1729)
|
||||
display_list = [' '] * SIZE
|
||||
occurrences = collections.Counter()
|
||||
for i in range(SIZE):
|
||||
new_item = random.randrange(SIZE*2)
|
||||
pos = target_list.index(new_item) + occurrences[new_item]
|
||||
occurrences[new_item] += 1
|
||||
display_list[pos] = '%2s, ' % new_item
|
||||
print('[' + ''.join(display_list) + ']')
|
||||
|
||||
29
attic/sequences/bisect_find.py
Normal file
29
attic/sequences/bisect_find.py
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
"""
|
||||
>>> bisect_find([], 1)
|
||||
-1
|
||||
>>> import array
|
||||
>>> import random
|
||||
>>> SIZE = 10
|
||||
>>> my_array = array.array('l', range(0, SIZE, 2))
|
||||
>>> random.seed(42)
|
||||
>>> for i in range(SIZE):
|
||||
... print(i, bisect_find(my_array, i))
|
||||
0 0
|
||||
1 -1
|
||||
2 1
|
||||
3 -1
|
||||
4 2
|
||||
5 -1
|
||||
6 3
|
||||
7 -1
|
||||
8 4
|
||||
9 -1
|
||||
"""
|
||||
|
||||
from bisect import bisect
|
||||
|
||||
def bisect_find(seq, item):
|
||||
left_pos = bisect(seq, item) - 1
|
||||
return left_pos if seq and seq[left_pos] == item else -1
|
||||
|
||||
29
attic/sequences/bisect_in.py
Normal file
29
attic/sequences/bisect_in.py
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
"""
|
||||
>>> bisect_in([], 1)
|
||||
False
|
||||
>>> import array
|
||||
>>> import random
|
||||
>>> SIZE = 10
|
||||
>>> my_array = array.array('l', range(0, SIZE, 2))
|
||||
>>> random.seed(42)
|
||||
>>> for i in range(SIZE):
|
||||
... print(i, bisect_in(my_array, i))
|
||||
0 True
|
||||
1 False
|
||||
2 True
|
||||
3 False
|
||||
4 True
|
||||
5 False
|
||||
6 True
|
||||
7 False
|
||||
8 True
|
||||
9 False
|
||||
"""
|
||||
|
||||
from bisect import bisect
|
||||
|
||||
def bisect_in(seq, item):
|
||||
pos = bisect(seq, item)
|
||||
return seq[pos-1] == item if seq else False
|
||||
|
||||
32
attic/sequences/bisect_time.py
Normal file
32
attic/sequences/bisect_time.py
Normal file
@@ -0,0 +1,32 @@
|
||||
"""
|
||||
bisect_time.py
|
||||
"""
|
||||
|
||||
import timeit
|
||||
|
||||
SETUP = '''
|
||||
SIZE = 10**6
|
||||
import array
|
||||
import random
|
||||
from bisect_find import bisect_find
|
||||
random.seed(42)
|
||||
haystack = [random.randrange(SIZE)*2 for i in range(SIZE)]
|
||||
needles = [random.choice(haystack) + i % 2 for i in range(20)]
|
||||
'''
|
||||
|
||||
BISECT = '''
|
||||
print('bisect:', end=' ')
|
||||
for n in needles:
|
||||
print(bisect_find(haystack, n), end=' ')
|
||||
print()
|
||||
'''
|
||||
|
||||
SORT = '''
|
||||
print(' in:', end=' ')
|
||||
for n in needles:
|
||||
print(int(n in haystack), end=' ')
|
||||
print()
|
||||
'''
|
||||
|
||||
print(min(timeit.Timer(BISECT, SETUP).repeat(7, 1)))
|
||||
print(min(timeit.Timer(SORT, SETUP).repeat(7, 1)))
|
||||
BIN
attic/sequences/dis_iadd_to_item.ods
Normal file
BIN
attic/sequences/dis_iadd_to_item.ods
Normal file
Binary file not shown.
10
attic/sequences/dis_iadd_to_item.txt
Normal file
10
attic/sequences/dis_iadd_to_item.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
1 0 LOAD_NAME 0 (s)
|
||||
3 LOAD_NAME 1 (a)
|
||||
6 DUP_TOP_TWO
|
||||
7 BINARY_SUBSCR <1>
|
||||
8 LOAD_NAME 2 (b)
|
||||
11 INPLACE_ADD <2>
|
||||
12 ROT_THREE
|
||||
13 STORE_SUBSCR <3>
|
||||
14 LOAD_CONST 0 (None)
|
||||
17 RETURN_VALUE
|
||||
54
attic/sequences/frenchdeck2.doctest
Normal file
54
attic/sequences/frenchdeck2.doctest
Normal file
@@ -0,0 +1,54 @@
|
||||
>>> from frenchdeck2 import FrenchDeck2, Card
|
||||
>>> beer_card = Card('7', 'diamonds')
|
||||
>>> beer_card
|
||||
Card(rank='7', suit='diamonds')
|
||||
>>> deck = FrenchDeck2()
|
||||
>>> len(deck)
|
||||
52
|
||||
>>> deck[:3]
|
||||
[Card(rank='2', suit='spades'), Card(rank='3', suit='spades'), Card(rank='4', suit='spades')]
|
||||
>>> deck[12::13]
|
||||
[Card(rank='A', suit='spades'), Card(rank='A', suit='diamonds'), Card(rank='A', suit='clubs'), Card(rank='A', suit='hearts')]
|
||||
>>> Card('Q', 'hearts') in deck
|
||||
True
|
||||
>>> Card('Z', 'clubs') in deck
|
||||
False
|
||||
>>> for card in deck: # doctest: +ELLIPSIS
|
||||
... print(card)
|
||||
Card(rank='2', suit='spades')
|
||||
Card(rank='3', suit='spades')
|
||||
Card(rank='4', suit='spades')
|
||||
...
|
||||
>>> for card in reversed(deck): # doctest: +ELLIPSIS
|
||||
... print(card)
|
||||
Card(rank='A', suit='hearts')
|
||||
Card(rank='K', suit='hearts')
|
||||
Card(rank='Q', suit='hearts')
|
||||
...
|
||||
>>> for n, card in enumerate(deck, 1): # doctest: +ELLIPSIS
|
||||
... print(n, card)
|
||||
1 Card(rank='2', suit='spades')
|
||||
2 Card(rank='3', suit='spades')
|
||||
3 Card(rank='4', suit='spades')
|
||||
...
|
||||
>>> def alt_color_rank(card):
|
||||
... rank_value = FrenchDeck2.ranks.index(card.rank)
|
||||
... suits = 'diamonds clubs hearts spades'.split()
|
||||
... return rank_value * len(suits) + suits.index(card.suit)
|
||||
|
||||
Rank test:
|
||||
|
||||
>>> alt_color_rank(Card('2', 'diamonds'))
|
||||
0
|
||||
>>> alt_color_rank(Card('A', 'spades'))
|
||||
51
|
||||
|
||||
>>> for card in sorted(deck, key=alt_color_rank): # doctest: +ELLIPSIS
|
||||
... print(card)
|
||||
Card(rank='2', suit='diamonds')
|
||||
Card(rank='2', suit='clubs')
|
||||
Card(rank='2', suit='hearts')
|
||||
...
|
||||
Card(rank='A', suit='clubs')
|
||||
Card(rank='A', suit='hearts')
|
||||
Card(rank='A', suit='spades')
|
||||
26
attic/sequences/frenchdeck2.py
Normal file
26
attic/sequences/frenchdeck2.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import collections
|
||||
|
||||
Card = collections.namedtuple('Card', ['rank', 'suit'])
|
||||
|
||||
class FrenchDeck2(collections.MutableSequence):
|
||||
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
|
||||
suits = 'spades diamonds clubs hearts'.split()
|
||||
|
||||
def __init__(self):
|
||||
self._cards = [Card(rank, suit) for suit in self.suits
|
||||
for rank in self.ranks]
|
||||
|
||||
def __len__(self):
|
||||
return len(self._cards)
|
||||
|
||||
def __getitem__(self, position):
|
||||
return self._cards[position]
|
||||
|
||||
def __setitem__(self, position, value): # <1>
|
||||
self._cards[position] = value
|
||||
|
||||
def __delitem__(self, position): # <2>
|
||||
del self._cards[position]
|
||||
|
||||
def insert(self, position, value): # <3>
|
||||
self._cards.insert(position, value)
|
||||
49
attic/sequences/metro_areas.py
Normal file
49
attic/sequences/metro_areas.py
Normal file
@@ -0,0 +1,49 @@
|
||||
FILENAME = 'metro_areas.txt'
|
||||
|
||||
class MetroArea:
|
||||
|
||||
def __init__(self, name, country, pop, pop_change, area):
|
||||
self.name = name
|
||||
self.country = country
|
||||
self.pop = pop
|
||||
self.pop_change = pop_change
|
||||
self.area = area
|
||||
|
||||
def __repr__(self):
|
||||
return '{0.name}, {0.country} ({0.pop})'.format(self)
|
||||
|
||||
def density(self):
|
||||
return self.pop / self.area
|
||||
|
||||
|
||||
def load():
|
||||
metro_areas = []
|
||||
with open(FILENAME, encoding='utf-8') as text:
|
||||
for line in text:
|
||||
if line.startswith('#'):
|
||||
continue
|
||||
# Country Name Rank Population Yr_change % Area(km2) Pop/km2
|
||||
country, name, _, pop, pop_change, _, area, _ = line.split('\t')
|
||||
pop = float(pop.replace(',', ''))
|
||||
pop_change = float(pop_change)
|
||||
area = float(area)
|
||||
metro_areas.append((name, country, pop, pop_change, area))
|
||||
return metro_areas
|
||||
|
||||
|
||||
def list(metro_areas):
|
||||
print('{:^18} {:>6} {:>4} {:>6}'.format('name', 'cc', 'pop', 'chg', 'area'))
|
||||
for metro in metro_areas:
|
||||
print('{:18} {:2} {:6.0f} {:4.0f} {:6.0f}'.format(*metro))
|
||||
|
||||
def list_instances(metro_areas):
|
||||
metro_areas = [MetroArea(*fields) for fields in metro_areas]
|
||||
for metro in metro_areas:
|
||||
print(metro)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
#list(load())
|
||||
list_instances(load())
|
||||
|
||||
|
||||
29
attic/sequences/metro_areas.txt
Normal file
29
attic/sequences/metro_areas.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
# THE 20 LARGEST WORLD METROPOLITAN AREAS, 2003: DATA FOR FORSTALL DEFINITIONS
|
||||
# (Populations in thousands estimated for 1 July 2003.)
|
||||
# CC Name Rank Population Yr_change % Area(km2) Pop/km2
|
||||
JP Tokyo 1 32,450 213 0.66 8014 4049.2
|
||||
KR Seoul 2 20,550 227 1.12 5076 4048.5
|
||||
MX Mexico City 3 20,450 307 1.54 7346 2783.8
|
||||
US New York 4 19,750 120 0.61 17884 1104.3
|
||||
IN Mumbai (Bombay) 5 19,200 472 2.53 2350 8170.2
|
||||
ID Jakarta 6 18,900 225 1.21 5100 3705.9
|
||||
BR Sao Paulo 7 18,850 289 1.57 8479 2223.1
|
||||
IN Delhi-New Delhi 8 18,600 686 3.86 3182 5845.4
|
||||
JP Osaka-Kobe-Kyoto 9 17,375 28 0.16 6930 2507.2
|
||||
CN Shanghai 10 16,650 335 2.07 5177 3216.1
|
||||
PH Manila 11 16,300 461 2.96 2521 6465.7
|
||||
CN Hong Kong-Shenzhen 12 15,800 797 5.42 3051 5178.6
|
||||
US Los Angeles 13 15,250 205 1.38 10780 1414.7
|
||||
IN Kolkata (Calcutta) 14 15,100 257 1.74 1785 8459.4
|
||||
RU Moscow 15 15,000 103 0.69 14925 1005.0
|
||||
EG Cairo 16 14,450 257 1.89 1600 9031.3
|
||||
AR Buenos Aires 17 13,170 79 0.62 10888 1209.6
|
||||
UK London 18 12,875 112 0.87 11391 1130.3
|
||||
CN Beijing 19 12,500 301 2.49 6562 1904.9
|
||||
PK Karachi 20 11,800 370 3.43 1100 10727.3
|
||||
# Data source:
|
||||
# WHICH ARE THE LARGEST? WHY PUBLISHED POPULATIONS
|
||||
# FOR MAJOR WORLD URBAN AREAS VARY SO GREATLY
|
||||
# Richard L. Forstall, Richard P. Greene, James B. Pick
|
||||
# http://web.archive.org/web/20130114203922/http://www.uic.edu/cuppa/cityfutures/papers/webpapers/cityfuturespapers/session3_4/3_4whicharethe.pdf
|
||||
# Country codes added by L. Ramalho
|
||||
21
attic/sequences/named_slices.py
Normal file
21
attic/sequences/named_slices.py
Normal file
@@ -0,0 +1,21 @@
|
||||
invoice = """
|
||||
0.....6.................................40........52...55........
|
||||
1909 Pimoroni PiBrella $17.50 3 $52.50
|
||||
1489 6mm Tactile Switch x20 $4.95 2 $9.90
|
||||
1510 Panavise Jr. - PV-201 $28.00 1 $28.00
|
||||
1601 PiTFT Mini Kit 320x240 $34.95 1 $34.95
|
||||
"""
|
||||
|
||||
structure = dict(
|
||||
SKU = slice(0, 6),
|
||||
DESCRIPTION = slice(6, 40),
|
||||
UNIT_PRICE = slice(40, 52),
|
||||
QUANTITY = slice(52, 55),
|
||||
ITEM_TOTAL = slice(55, None),
|
||||
)
|
||||
|
||||
for line in invoice.split('\n')[2:]:
|
||||
line_item = {}
|
||||
for field, chunk in structure.items():
|
||||
line_item[field] = line[chunk].strip()
|
||||
print(line_item)
|
||||
75
attic/sequences/sentence.doctest
Normal file
75
attic/sequences/sentence.doctest
Normal file
@@ -0,0 +1,75 @@
|
||||
>>> from sentence import Sentence
|
||||
>>> s = Sentence('The time has come')
|
||||
>>> s
|
||||
Sentence('The time has come')
|
||||
>>> s[0]
|
||||
'The'
|
||||
>>> list(s)
|
||||
['The', 'time', 'has', 'come']
|
||||
|
||||
|
||||
>>> s = Sentence('"The time has come," the Walrus said,')
|
||||
>>> s
|
||||
Sentence('"The time ha... Walrus said,')
|
||||
>>> s[0]
|
||||
'The'
|
||||
>>> s[1]
|
||||
'time'
|
||||
>>> for word in s:
|
||||
... print(word)
|
||||
The
|
||||
time
|
||||
has
|
||||
come
|
||||
the
|
||||
Walrus
|
||||
said
|
||||
>>> list(s)
|
||||
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said']
|
||||
>>> s[-2]
|
||||
'Walrus'
|
||||
>>> s[2:4]
|
||||
['has', 'come']
|
||||
>>> s[:4]
|
||||
['The', 'time', 'has', 'come']
|
||||
>>> s[4:]
|
||||
['the', 'Walrus', 'said']
|
||||
|
||||
|
||||
>>> s3 = Sentence('Pig and Pepper')
|
||||
>>> it = iter(s3)
|
||||
>>> it # doctest: +ELLIPSIS
|
||||
<iterator object at 0x...>
|
||||
>>> next(it)
|
||||
'Pig'
|
||||
>>> next(it)
|
||||
'and'
|
||||
>>> next(it)
|
||||
'Pepper'
|
||||
>>> next(it)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
StopIteration
|
||||
>>> list(it)
|
||||
[]
|
||||
>>> list(iter(s3))
|
||||
['Pig', 'and', 'Pepper']
|
||||
|
||||
|
||||
>>> s = Sentence('''The right of the people to be secure in
|
||||
... their persons, houses, papers, and effects, against
|
||||
... unreasonable searches and seizures, shall not be violated,''')
|
||||
>>> s
|
||||
Sentence('The right of... be violated,')
|
||||
>>> list(s) # doctest: +ELLIPSIS
|
||||
['The', 'right', 'of', 'the', 'people', ... 'not', 'be', 'violated']
|
||||
|
||||
|
||||
>>> s = Sentence('Agora vou-me. Ou me vão?')
|
||||
>>> s
|
||||
Sentence('Agora vou-me. Ou me vão?')
|
||||
>>> list(s)
|
||||
['Agora', 'vou', 'me', 'Ou', 'me', 'vão']
|
||||
|
||||
|
||||
|
||||
24
attic/sequences/sentence.py
Normal file
24
attic/sequences/sentence.py
Normal file
@@ -0,0 +1,24 @@
|
||||
"""
|
||||
Sentence: access words by index
|
||||
"""
|
||||
|
||||
import re
|
||||
import reprlib
|
||||
|
||||
RE_WORD = re.compile('\w+')
|
||||
|
||||
|
||||
class Sentence:
|
||||
|
||||
def __init__(self, text):
|
||||
self.text = text
|
||||
self.words = RE_WORD.findall(text) # <1>
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self.words[index] # <2>
|
||||
|
||||
def __len__(self, index): # <3>
|
||||
return len(self.words)
|
||||
|
||||
def __repr__(self):
|
||||
return 'Sentence(%s)' % reprlib.repr(self.text) # <4>
|
||||
79
attic/sequences/sentence_slice.doctest
Normal file
79
attic/sequences/sentence_slice.doctest
Normal file
@@ -0,0 +1,79 @@
|
||||
>>> from sentence_slice import SentenceSlice
|
||||
>>> s = SentenceSlice('the')
|
||||
>>> s.tokens
|
||||
['the']
|
||||
>>> s.words
|
||||
['the']
|
||||
|
||||
>>> s = SentenceSlice('the quick brown fox')
|
||||
>>> s.tokens
|
||||
['the', ' ', 'quick', ' ', 'brown', ' ', 'fox']
|
||||
>>> s.words
|
||||
['the', 'quick', 'brown', 'fox']
|
||||
>>> s[0]
|
||||
'the'
|
||||
>>> s[1]
|
||||
'quick'
|
||||
>>> s[-1]
|
||||
'fox'
|
||||
>>> s[2:4]
|
||||
SentenceSlice('brown fox')
|
||||
>>> s[1:]
|
||||
SentenceSlice('quick brown fox')
|
||||
>>> s[:3]
|
||||
SentenceSlice('the quick brown')
|
||||
|
||||
>>> s = SentenceSlice('"The time has come," the Walrus said,')
|
||||
>>> s.tokens
|
||||
['"', 'The', ' ', 'time', ' ', 'has', ' ', 'come', ',"', ' ', 'the', ' ', 'Walrus', ' ', 'said', ',']
|
||||
>>> s.words
|
||||
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said']
|
||||
>>> s[:3]
|
||||
SentenceSlice('"The time has')
|
||||
>>> s[:4]
|
||||
SentenceSlice('"The time has come,"')
|
||||
>>> s[4:]
|
||||
SentenceSlice('the Walrus said,')
|
||||
>>> s[1:5]
|
||||
SentenceSlice('time has come," the')
|
||||
>>> s[1:6]
|
||||
SentenceSlice('time has come," the Walrus')
|
||||
>>> s[1:7]
|
||||
SentenceSlice('time has com... Walrus said,')
|
||||
>>> s[1:8]
|
||||
SentenceSlice('time has com... Walrus said,')
|
||||
>>> s[6:]
|
||||
SentenceSlice('said,')
|
||||
>>> s[7:]
|
||||
SentenceSlice('')
|
||||
>>> s[8:]
|
||||
SentenceSlice('')
|
||||
>>> s[:-3]
|
||||
SentenceSlice('"The time has come,"')
|
||||
>>> s[-4:-2]
|
||||
SentenceSlice('come," the')
|
||||
>>> s[0:2]
|
||||
SentenceSlice('"The time')
|
||||
|
||||
>>> s = SentenceSlice('''"The time has come," the Walrus said,
|
||||
... "To talk of many things:"''')
|
||||
>>> s.tokens
|
||||
['"', 'The', ' ', 'time', ' ', 'has', ' ', 'come', ',"', ' ', 'the', ' ', 'Walrus', ' ', 'said', ',', '\n', '"', 'To', ' ', 'talk', ' ', 'of', ' ', 'many', ' ', 'things', ':"']
|
||||
>>> s.words
|
||||
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said', 'To', 'talk', 'of', 'many', 'things']
|
||||
|
||||
>>> s = SentenceSlice('Agora vou-me. Ou me vão?')
|
||||
>>> s.tokens
|
||||
['Agora', ' ', 'vou', '-', 'me', '.', ' ', 'Ou', ' ', 'me', ' ', 'vão', '?']
|
||||
>>> s.words
|
||||
['Agora', 'vou', 'me', 'Ou', 'me', 'vão']
|
||||
>>> s[1:]
|
||||
SentenceSlice('vou-me. Ou me vão?')
|
||||
>>> s[:2]
|
||||
SentenceSlice('Agora vou-')
|
||||
>>> s[2:]
|
||||
SentenceSlice('-me. Ou me vão?')
|
||||
|
||||
|
||||
|
||||
|
||||
66
attic/sequences/sentence_slice.py
Normal file
66
attic/sequences/sentence_slice.py
Normal file
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
SentenceSlice: access words by index, sub-sentences by slices
|
||||
"""
|
||||
|
||||
import re
|
||||
import reprlib
|
||||
|
||||
|
||||
RE_TOKEN = re.compile('\w+|\s+|[^\w\s]+')
|
||||
RE_WORD = re.compile('\w+')
|
||||
RE_PUNCTUATION = re.compile('[^\w\s]+')
|
||||
|
||||
|
||||
class SentenceSlice:
|
||||
|
||||
def __init__(self, text):
|
||||
self.text = text
|
||||
self.tokens = RE_TOKEN.findall(text)
|
||||
self.words = [t for t in self.tokens if RE_WORD.match(t)]
|
||||
self.word_index = [i for i, t in enumerate(self.tokens)
|
||||
if RE_WORD.match(t)]
|
||||
|
||||
def __repr__(self):
|
||||
return 'SentenceSlice(%s)' % reprlib.repr(self.text)
|
||||
|
||||
def __getitem__(self, position):
|
||||
if isinstance(position, slice):
|
||||
if position.step is not None:
|
||||
raise LookupError('slice step is not supported')
|
||||
start, stop = self._handle_defaults(position)
|
||||
start, stop = self._widen(start, stop)
|
||||
tokens = self.tokens[start:stop]
|
||||
return SentenceSlice(''.join(tokens))
|
||||
else:
|
||||
return self.words[position]
|
||||
|
||||
def __len__(self, index):
|
||||
return len(self.words)
|
||||
|
||||
# helper functions -- implementation detail
|
||||
def _handle_defaults(self, position):
|
||||
"""handle missing or overflow/underflow start/stop"""
|
||||
if position.start is None: # missing
|
||||
start = 0
|
||||
elif position.start >= len(self.word_index): # overflow
|
||||
start = len(self.tokens)
|
||||
else:
|
||||
start = self.word_index[position.start]
|
||||
if (position.stop is None # missing
|
||||
or position.stop > len(self.word_index)): # overflow
|
||||
stop = self.word_index[-1]
|
||||
else:
|
||||
stop = self.word_index[position.stop-1]
|
||||
return start, stop + 1 # stop after last word selected
|
||||
|
||||
def _widen(self, start, stop):
|
||||
"""widen range of tokens to get punctuation to the left of
|
||||
start and to the right of stop"""
|
||||
if start < len(self.tokens):
|
||||
while (start > 0 and
|
||||
RE_PUNCTUATION.match(self.tokens[start-1])):
|
||||
start -= 1
|
||||
while (stop < len(self.tokens) and
|
||||
RE_PUNCTUATION.match(self.tokens[stop])):
|
||||
stop += 1
|
||||
return start, stop
|
||||
33
attic/sequences/slice_dump.py
Normal file
33
attic/sequences/slice_dump.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""
|
||||
|
||||
>>> sd = SliceDump()
|
||||
>>> sd[1]
|
||||
1
|
||||
>>> sd[2:5]
|
||||
slice(2, 5, None)
|
||||
>>> sd[:2]
|
||||
slice(None, 2, None)
|
||||
>>> sd[7:]
|
||||
slice(7, None, None)
|
||||
>>> sd[:]
|
||||
slice(None, None, None)
|
||||
>>> sd[1:9:3]
|
||||
slice(1, 9, 3)
|
||||
>>> sd[1:9:3, 2:3]
|
||||
(slice(1, 9, 3), slice(2, 3, None))
|
||||
>>> s = sd[1:9:3]
|
||||
>>> s.indices(20)
|
||||
(1, 9, 3)
|
||||
>>> s.indices(5)
|
||||
(1, 5, 3)
|
||||
>>> s.indices(1)
|
||||
(1, 1, 3)
|
||||
>>> s.indices(0)
|
||||
(0, 0, 3)
|
||||
|
||||
"""
|
||||
|
||||
class SliceDump:
|
||||
|
||||
def __getitem__(self, pos):
|
||||
return pos
|
||||
38
attic/sequences/slice_test.py
Normal file
38
attic/sequences/slice_test.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
|
||||
>>> s = SliceDemo()
|
||||
>>> s[1]
|
||||
__getitem__: 1
|
||||
1
|
||||
>>> s[2:5]
|
||||
__getitem__: slice(2, 5, None)
|
||||
[2, 3, 4]
|
||||
>>> s[:2]
|
||||
__getitem__: slice(None, 2, None)
|
||||
[0, 1]
|
||||
>>> s[7:]
|
||||
__getitem__: slice(7, None, None)
|
||||
[7, 8, 9]
|
||||
>>> s[:]
|
||||
__getitem__: slice(None, None, None)
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
>>> s[1:9:3]
|
||||
__getitem__: slice(1, 9, 3)
|
||||
[1, 4, 7]
|
||||
>>> s[1:9:3, 2:3]
|
||||
__getitem__: (slice(1, 9, 3), slice(2, 3, None))
|
||||
ERROR: list indices must be integers, not tuple
|
||||
|
||||
"""
|
||||
|
||||
class SliceDemo:
|
||||
|
||||
def __init__(self):
|
||||
self.items = list(range(10))
|
||||
|
||||
def __getitem__(self, pos):
|
||||
print('__getitem__:', pos)
|
||||
try:
|
||||
return self.items.__getitem__(pos)
|
||||
except TypeError as e:
|
||||
print('ERROR:', e)
|
||||
38
attic/sequences/slice_viewer.py
Normal file
38
attic/sequences/slice_viewer.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
Extended slicing:
|
||||
|
||||
>>> s = SliceViewer()
|
||||
>>> s[1]
|
||||
1
|
||||
>>> s[:]
|
||||
slice(None, None, None)
|
||||
>>> s[1:2]
|
||||
slice(1, 2, None)
|
||||
>>> s[1:2:3]
|
||||
slice(1, 2, 3)
|
||||
>>> s[1:2:3:4]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
SyntaxError: invalid syntax
|
||||
|
||||
N-dimensional indexing:
|
||||
|
||||
>>> s[1, 2]
|
||||
(1, 2)
|
||||
|
||||
N-dimensional slicing:
|
||||
|
||||
>>> s[1:3, 2]
|
||||
(slice(1, 3, None), 2)
|
||||
>>> s[1, :2:]
|
||||
(1, slice(None, 2, None))
|
||||
>>> s[:, :]
|
||||
(slice(None, None, None), slice(None, None, None))
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class SliceViewer:
|
||||
|
||||
def __getitem__(self, position):
|
||||
return position
|
||||
43
attic/sequences/str_concat.py
Normal file
43
attic/sequences/str_concat.py
Normal file
@@ -0,0 +1,43 @@
|
||||
"""string concatenation demos"""
|
||||
|
||||
from time import perf_counter
|
||||
|
||||
def load_lines():
|
||||
with open('war-and-peace.txt') as fp:
|
||||
return fp.readlines() * 100 # replace with 200 or more for surprises!!!
|
||||
|
||||
def chrono(f):
|
||||
def inner(lines):
|
||||
t0 = perf_counter()
|
||||
text = f(lines)
|
||||
elapsed = perf_counter() - t0
|
||||
print('%15s: %fs' % (f.__name__, elapsed))
|
||||
return text
|
||||
return inner
|
||||
|
||||
@chrono
|
||||
def iadd_joiner(lines):
|
||||
text = ''
|
||||
for line in lines:
|
||||
text += line
|
||||
return text
|
||||
|
||||
@chrono
|
||||
def list_joiner(lines):
|
||||
parts = []
|
||||
for line in lines:
|
||||
parts.append(line)
|
||||
return ''.join(parts)
|
||||
|
||||
@chrono
|
||||
def genexp_joiner(lines):
|
||||
return ''.join(line for line in lines)
|
||||
|
||||
if __name__=='__main__':
|
||||
lines = load_lines()
|
||||
print('joining %s lines' % len(lines))
|
||||
text0 = iadd_joiner(lines)
|
||||
text1 = list_joiner(lines)
|
||||
text2 = genexp_joiner(lines)
|
||||
assert len(text0) == len(text1) == len(text2), repr(
|
||||
(len(text0), len(text1), len(text2)))
|
||||
173
attic/sequences/table.py
Normal file
173
attic/sequences/table.py
Normal file
@@ -0,0 +1,173 @@
|
||||
|
||||
"""
|
||||
=============
|
||||
Row tests
|
||||
=============
|
||||
|
||||
>>> row = Row([1, 2, 3, 4])
|
||||
>>> row[1]
|
||||
2
|
||||
>>> row[1:3]
|
||||
Row([2, 3])
|
||||
|
||||
=============
|
||||
Table tests
|
||||
=============
|
||||
|
||||
Create an empty table
|
||||
|
||||
>>> t3x4 = Table.blank(3, 4)
|
||||
>>> t3x4
|
||||
Table(Row([None, None, None, None]),
|
||||
Row([None, None, None, None]),
|
||||
Row([None, None, None, None]))
|
||||
>>> for i in range(3):
|
||||
... for j in range(4):
|
||||
... t3x4[i][j] = chr(65 + i * 4 + j)
|
||||
...
|
||||
>>> t3x4
|
||||
Table(Row(['A', 'B', 'C', 'D']),
|
||||
Row(['E', 'F', 'G', 'H']),
|
||||
Row(['I', 'J', 'K', 'L']))
|
||||
>>> t3x4[1]
|
||||
Row(['E', 'F', 'G', 'H'])
|
||||
>>> t3x4[1:]
|
||||
Table(Row(['E', 'F', 'G', 'H']),
|
||||
Row(['I', 'J', 'K', 'L']))
|
||||
|
||||
>>> t3x4[1][2]
|
||||
'G'
|
||||
>>> t3x4[1, 2]
|
||||
'G'
|
||||
|
||||
Slicing returns a table, so index 2 below would be trying to get row index 2
|
||||
of a table that has only rows 0 and 1:
|
||||
|
||||
>>> t3x4[1:][2]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
IndexError: no row at index 2 of 2-row table
|
||||
|
||||
>>> t3x4[:, 2]
|
||||
Table(Row(['C']),
|
||||
Row(['G']),
|
||||
Row(['K']))
|
||||
|
||||
>>> t3x4[1:, 2]
|
||||
Table(Row(['G']),
|
||||
Row(['K']))
|
||||
|
||||
>>> t3x4[1, 2:]
|
||||
Row(['G', 'H'])
|
||||
|
||||
>>> t3x4[:, 1:3]
|
||||
Table(Row(['B', 'C']),
|
||||
Row(['F', 'G']),
|
||||
Row(['J', 'K']))
|
||||
|
||||
>>> t3x4[:, :]
|
||||
Table(Row(['A', 'B', 'C', 'D']),
|
||||
Row(['E', 'F', 'G', 'H']),
|
||||
Row(['I', 'J', 'K', 'L']))
|
||||
|
||||
>>> t3x4[:, :] == t3x4
|
||||
True
|
||||
|
||||
===============
|
||||
Error handling
|
||||
===============
|
||||
|
||||
>>> t3x4[5]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
IndexError: no row at index 5 of 3-row table
|
||||
>>> t3x4[1,]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
IndexError: index must be [i] or [i, j]
|
||||
>>> t3x4[1, 2, 3]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
IndexError: index must be [i] or [i, j]
|
||||
>>> t3x4[10:, 2]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Table must have at least one row.
|
||||
>>> t3x4[1, 20:]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Row must have at least one cell.
|
||||
"""
|
||||
|
||||
import collections
|
||||
|
||||
|
||||
class Row(collections.UserList):
|
||||
|
||||
def __init__(self, cells):
|
||||
super().__init__(cells)
|
||||
if len(self) < 1:
|
||||
raise ValueError('Row must have at least one cell.')
|
||||
|
||||
def __getitem__(self, position):
|
||||
if isinstance(position, slice):
|
||||
return Row(self.data[position]) # build sub-row
|
||||
else:
|
||||
return self.data[position] # return cell value
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r)' % (self.__class__.__name__, self.data)
|
||||
|
||||
|
||||
class Table(collections.UserList):
|
||||
"""A table with rows, all of the same width"""
|
||||
|
||||
def __init__(self, rows):
|
||||
super().__init__(Row(r) for r in rows)
|
||||
if len(self) < 1:
|
||||
raise ValueError('Table must have at least one row.')
|
||||
self.width = self.check_width()
|
||||
|
||||
def check_width(self):
|
||||
row_widths = {len(row) for row in self.data}
|
||||
if len(row_widths) > 1:
|
||||
raise ValueError('All rows must have equal length.')
|
||||
return row_widths.pop()
|
||||
|
||||
@classmethod
|
||||
def blank(class_, rows, columns, filler=None):
|
||||
return class_([[filler] * columns for i in range(rows)])
|
||||
|
||||
def __repr__(self):
|
||||
prefix = '%s(' % self.__class__.__name__
|
||||
indent = ' ' * len(prefix)
|
||||
rows = (',\n' + indent).join(
|
||||
repr(row) for row in self.data)
|
||||
return prefix + rows + ')'
|
||||
|
||||
def _get_indexes(self, position):
|
||||
if isinstance(position, tuple): # multiple indexes
|
||||
if len(position) == 2: # two indexes: t[i, j]
|
||||
return position
|
||||
else:
|
||||
raise IndexError('index must be [i] or [i, j]')
|
||||
else: # one index: t[i]
|
||||
return position, None
|
||||
|
||||
def __getitem__(self, position):
|
||||
i, j = self._get_indexes(position)
|
||||
if isinstance(i, slice):
|
||||
if j is None: # build sub-table w/ full rows
|
||||
return Table(self.data[position])
|
||||
else: # build sub-table w/ sub-rows
|
||||
return Table(cells[j] for cells in self.data[i])
|
||||
else: # i is number
|
||||
try:
|
||||
row = self.data[i]
|
||||
except IndexError:
|
||||
msg = 'no row at index %r of %d-row table'
|
||||
raise IndexError(msg % (position, len(self)))
|
||||
if j is None: # return row at table[i]
|
||||
return row
|
||||
else:
|
||||
return row[j] # return row[j] or row[a:b]
|
||||
14
attic/sequences/tuples.doctest
Normal file
14
attic/sequences/tuples.doctest
Normal file
@@ -0,0 +1,14 @@
|
||||
>>> coordinates = (-23.547778, -46.635833)
|
||||
>>> lat, long_ = coordinates
|
||||
>>> long_
|
||||
-46.635833
|
||||
>>> lat
|
||||
-23.547778
|
||||
>>> traveler_ids = [('USA', '311975855'), ('BRA', 'CE342567'), ('ESP', 'XDA205856')]
|
||||
>>> for country, passport_no in sorted(traveler_ids):
|
||||
... print('%s:%s' % (country, passport_no))
|
||||
BRA:CE342567
|
||||
ESP:XDA205856
|
||||
USA:311975855
|
||||
|
||||
|
||||
65007
attic/sequences/war-and-peace.txt
Normal file
65007
attic/sequences/war-and-peace.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user