Mastering Python Second Edition Release Code
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
Chapter 3, Containers and Collections
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
| Storing Data the Right Way using the many containers and collections bundled with Python to create code that is fast and readable.
|
||||
@@ -0,0 +1,34 @@
|
||||
>>> n = 1000
|
||||
>>> a = list(range(n))
|
||||
>>> b = dict.fromkeys(range(n))
|
||||
>>> for i in range(100):
|
||||
... assert i in a # takes n=1000 steps
|
||||
... assert i in b # takes 1 step
|
||||
|
||||
|
||||
>>> def o_one(items):
|
||||
... return 1 # 1 operation so O(1)
|
||||
|
||||
>>> def o_n(items):
|
||||
... total = 0
|
||||
... # Walks through all items once so O(n)
|
||||
... for item in items:
|
||||
... total += item
|
||||
... return total
|
||||
|
||||
>>> def o_n_squared(items):
|
||||
... total = 0
|
||||
... # Walks through all items n*n times so O(n**2)
|
||||
... for a in items:
|
||||
... for b in items:
|
||||
... total += a * b
|
||||
... return total
|
||||
|
||||
>>> n = 10
|
||||
>>> items = range(n)
|
||||
>>> o_one(items) # 1 operation
|
||||
1
|
||||
>>> o_n(items) # n = 10 operations
|
||||
45
|
||||
>>> o_n_squared(items) # n*n = 10*10 = 100 operations
|
||||
2025
|
||||
@@ -0,0 +1,89 @@
|
||||
>>> def remove(items, value):
|
||||
... new_items = []
|
||||
... found = False
|
||||
... for item in items:
|
||||
... # Skip the first item which is equal to value
|
||||
... if not found and item == value:
|
||||
... found = True
|
||||
... continue
|
||||
... new_items.append(item)
|
||||
...
|
||||
... if not found:
|
||||
... raise ValueError('list.remove(x): x not in list')
|
||||
...
|
||||
... return new_items
|
||||
|
||||
|
||||
>>> def insert(items, index, value):
|
||||
... new_items = []
|
||||
... for i, item in enumerate(items):
|
||||
... if i == index:
|
||||
... new_items.append(value)
|
||||
... new_items.append(item)
|
||||
... return new_items
|
||||
|
||||
>>> items = list(range(10))
|
||||
>>> items
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
>>> items = remove(items, 5)
|
||||
>>> items
|
||||
[0, 1, 2, 3, 4, 6, 7, 8, 9]
|
||||
|
||||
>>> items = insert(items, 2, 5)
|
||||
>>> items
|
||||
[0, 1, 5, 2, 3, 4, 6, 7, 8, 9]
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> primes = set((1, 2, 3, 5, 7))
|
||||
|
||||
# Classic solution
|
||||
|
||||
>>> items = list(range(10))
|
||||
>>> for prime in primes:
|
||||
... items.remove(prime)
|
||||
>>> items
|
||||
[0, 4, 6, 8, 9]
|
||||
|
||||
# List comprehension
|
||||
|
||||
>>> items = list(range(10))
|
||||
>>> [item for item in items if item not in primes]
|
||||
[0, 4, 6, 8, 9]
|
||||
|
||||
# Filter
|
||||
|
||||
>>> items = list(range(10))
|
||||
>>> list(filter(lambda item: item not in primes, items))
|
||||
[0, 4, 6, 8, 9]
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> def in_(items, value):
|
||||
... for item in items:
|
||||
... if item == value:
|
||||
... return True
|
||||
... return False
|
||||
|
||||
>>> def min_(items):
|
||||
... current_min = items[0]
|
||||
... for item in items[1:]:
|
||||
... if current_min > item:
|
||||
... current_min = item
|
||||
... return current_min
|
||||
|
||||
>>> def max_(items):
|
||||
... current_max = items[0]
|
||||
... for item in items[1:]:
|
||||
... if current_max < item:
|
||||
... current_max = item
|
||||
... return current_max
|
||||
|
||||
>>> items = range(5)
|
||||
>>> in_(items, 3)
|
||||
True
|
||||
>>> min_(items)
|
||||
0
|
||||
>>> max_(items)
|
||||
4
|
||||
@@ -0,0 +1,48 @@
|
||||
>>> def most_significant(value):
|
||||
... while value >= 10:
|
||||
... value //= 10
|
||||
... return value
|
||||
|
||||
>>> most_significant(12345)
|
||||
1
|
||||
>>> most_significant(99)
|
||||
9
|
||||
>>> most_significant(0)
|
||||
0
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> def add(collection, key, value):
|
||||
... index = most_significant(key)
|
||||
... collection[index].append((key, value))
|
||||
|
||||
>>> def contains(collection, key):
|
||||
... index = most_significant(key)
|
||||
... for k, v in collection[index]:
|
||||
... if k == key:
|
||||
... return True
|
||||
... return False
|
||||
|
||||
# Create the collection of 10 lists
|
||||
|
||||
>>> collection = [[], [], [], [], [], [], [], [], [], []]
|
||||
|
||||
# Add some items, using key/value pairs
|
||||
|
||||
>>> add(collection, 123, 'a')
|
||||
>>> add(collection, 456, 'b')
|
||||
>>> add(collection, 789, 'c')
|
||||
>>> add(collection, 101, 'c')
|
||||
|
||||
# Look at the collection
|
||||
|
||||
>>> collection
|
||||
[[], [(123, 'a'), (101, 'c')], [], [],
|
||||
[(456, 'b')], [], [], [(789, 'c')], [], []]
|
||||
|
||||
# Check if the contains works correctly
|
||||
|
||||
>>> contains(collection, 123)
|
||||
True
|
||||
>>> contains(collection, 1)
|
||||
False
|
||||
@@ -0,0 +1,38 @@
|
||||
# All output in the table below is generated using this function
|
||||
|
||||
>>> def print_set(expression, set_):
|
||||
... 'Print set as a string sorted by letters'
|
||||
... print(expression, ''.join(sorted(set_)))
|
||||
|
||||
>>> spam = set('spam')
|
||||
>>> print_set('spam:', spam)
|
||||
spam: amps
|
||||
|
||||
>>> eggs = set('eggs')
|
||||
>>> print_set('eggs:', eggs)
|
||||
eggs: egs
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> current_users = set((
|
||||
... 'a',
|
||||
... 'b',
|
||||
... 'd',
|
||||
... ))
|
||||
|
||||
>>> new_users = set((
|
||||
... 'b',
|
||||
... 'c',
|
||||
... 'd',
|
||||
... 'e',
|
||||
... ))
|
||||
|
||||
>>> to_insert = new_users - current_users
|
||||
>>> sorted(to_insert)
|
||||
['c', 'e']
|
||||
>>> to_delete = current_users - new_users
|
||||
>>> sorted(to_delete)
|
||||
['a']
|
||||
>>> unchanged = new_users & current_users
|
||||
>>> sorted(unchanged)
|
||||
['b', 'd']
|
||||
@@ -0,0 +1,99 @@
|
||||
>>> spam = 1, 2, 3
|
||||
>>> eggs = 4, 5, 6
|
||||
|
||||
>>> data = dict()
|
||||
>>> data[spam] = 'spam'
|
||||
>>> data[eggs] = 'eggs'
|
||||
|
||||
>>> import pprint # Using pprint for consistent and sorted output
|
||||
|
||||
>>> pprint.pprint(data)
|
||||
{(1, 2, 3): 'spam', (4, 5, 6): 'eggs'}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> spam = 1, 'abc', (2, 3, (4, 5)), 'def'
|
||||
>>> eggs = 4, (spam, 5), 6
|
||||
|
||||
>>> data = dict()
|
||||
>>> data[spam] = 'spam'
|
||||
>>> data[eggs] = 'eggs'
|
||||
>>> import pprint # Using pprint for consistent and sorted output
|
||||
|
||||
>>> pprint.pprint(data)
|
||||
{(1, 'abc', (2, 3, (4, 5)), 'def'): 'spam',
|
||||
(4, ((1, 'abc', (2, 3, (4, 5)), 'def'), 5), 6): 'eggs'}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
# Assign using tuples on both sides
|
||||
|
||||
>>> a, b, c = 1, 2, 3
|
||||
>>> a
|
||||
1
|
||||
|
||||
# Assign a tuple to a single variable
|
||||
|
||||
>>> spam = a, (b, c)
|
||||
>>> spam
|
||||
(1, (2, 3))
|
||||
|
||||
# Unpack a tuple to two variables
|
||||
|
||||
>>> a, b = spam
|
||||
>>> a
|
||||
1
|
||||
>>> b
|
||||
(2, 3)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
# Unpack with variable length objects which assigns a list instead
|
||||
of a tuple
|
||||
|
||||
>>> spam, *eggs = 1, 2, 3, 4
|
||||
>>> spam
|
||||
1
|
||||
>>> eggs
|
||||
[2, 3, 4]
|
||||
|
||||
# Which can be unpacked as well of course
|
||||
|
||||
>>> a, b, c = eggs
|
||||
>>> c
|
||||
4
|
||||
|
||||
# This works for ranges as well
|
||||
|
||||
>>> spam, *eggs = range(10)
|
||||
>>> spam
|
||||
0
|
||||
>>> eggs
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
# And it works both ways
|
||||
|
||||
>>> a, b, *c = a, *eggs
|
||||
>>> a, b
|
||||
(2, 1)
|
||||
>>> c
|
||||
[2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> def eggs(*args):
|
||||
... print('args:', args)
|
||||
|
||||
>>> eggs(1, 2, 3)
|
||||
args: (1, 2, 3)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> def spam_eggs():
|
||||
... return 'spam', 'eggs'
|
||||
|
||||
>>> spam, eggs = spam_eggs()
|
||||
>>> spam
|
||||
'spam'
|
||||
>>> eggs
|
||||
'eggs'
|
||||
@@ -0,0 +1,59 @@
|
||||
>>> spam: int
|
||||
>>> __annotations__['spam']
|
||||
<class 'int'>
|
||||
>>> spam = 'not a number'
|
||||
>>> __annotations__['spam']
|
||||
<class 'int'>
|
||||
|
||||
|
||||
>>> import dataclasses
|
||||
|
||||
>>> @dataclasses.dataclass
|
||||
... class Sandwich:
|
||||
... spam: int
|
||||
... eggs: int = 3
|
||||
|
||||
>>> Sandwich(1, 2)
|
||||
Sandwich(spam=1, eggs=2)
|
||||
|
||||
>>> sandwich = Sandwich(4)
|
||||
>>> sandwich
|
||||
Sandwich(spam=4, eggs=3)
|
||||
>>> sandwich.eggs
|
||||
3
|
||||
>>> dataclasses.asdict(sandwich)
|
||||
{'spam': 4, 'eggs': 3}
|
||||
>>> dataclasses.astuple(sandwich)
|
||||
(4, 3)
|
||||
|
||||
>>> help(dataclasses.dataclass)
|
||||
Help on ... dataclass(..., *, init=True, repr=True, eq=True, ...
|
||||
|
||||
>>> def __init__(self, spam, eggs=3):
|
||||
... self.spam = spam
|
||||
... self.eggs = eggs
|
||||
|
||||
|
||||
>>> import typing
|
||||
|
||||
>>> @dataclasses.dataclass
|
||||
... class Group:
|
||||
... name: str
|
||||
... parent: 'Group' = None
|
||||
|
||||
>>> @dataclasses.dataclass
|
||||
... class User:
|
||||
... username: str
|
||||
... email: str = None
|
||||
... groups: typing.List[Group] = None
|
||||
|
||||
>>> users = Group('users')
|
||||
>>> admins = Group('admins', users)
|
||||
>>> rick = User('rick', groups=[admins])
|
||||
>>> gvr = User('gvanrossum', 'guido@python.org', [admins])
|
||||
|
||||
>>> rick.groups
|
||||
[Group(name='admins', parent=Group(name='users', parent=None))]
|
||||
|
||||
>>> rick.groups[0].parent
|
||||
Group(name='users', parent=None)
|
||||
@@ -0,0 +1,74 @@
|
||||
>>> import builtins
|
||||
|
||||
>>> builtin_vars = vars(builtins)
|
||||
|
||||
>>> key = 'something to search for'
|
||||
|
||||
>>> if key in locals():
|
||||
... value = locals()[key]
|
||||
... elif key in globals():
|
||||
... value = globals()[key]
|
||||
... elif key in builtin_vars:
|
||||
... value = builtin_vars[key]
|
||||
... else:
|
||||
... raise NameError(f'name {key!r} is not defined')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
NameError: name 'something to search for' is not defined
|
||||
|
||||
##############################################################################
|
||||
|
||||
>>> mappings = locals(), globals(), vars(builtins)
|
||||
>>> for mapping in mappings:
|
||||
... if key in mapping:
|
||||
... value = mapping[key]
|
||||
... break
|
||||
... else:
|
||||
... raise NameError(f'name {key!r} is not defined')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
NameError: name 'something to search for' is not defined
|
||||
|
||||
##############################################################################
|
||||
|
||||
>>> import collections
|
||||
|
||||
>>> mappings = collections.ChainMap(
|
||||
... locals(), globals(), vars(builtins))
|
||||
>>> mappings[key]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 'something to search for'
|
||||
|
||||
##############################################################################
|
||||
|
||||
>>> import json
|
||||
>>> import pathlib
|
||||
>>> import argparse
|
||||
>>> import collections
|
||||
|
||||
>>> DEFAULT = dict(verbosity=1)
|
||||
|
||||
>>> config_file = pathlib.Path('config.json')
|
||||
>>> if config_file.exists():
|
||||
... config = json.load(config_file.open())
|
||||
... else:
|
||||
... config = dict()
|
||||
|
||||
>>> parser = argparse.ArgumentParser()
|
||||
>>> parser.add_argument('-v', '--verbose', action='count',
|
||||
... dest='verbosity')
|
||||
_CountAction(...)
|
||||
|
||||
>>> args, _ = parser.parse_known_args(args=['-v'])
|
||||
>>> defined_args = {k: v for k, v in vars(args).items() if v}
|
||||
>>> combined = collections.ChainMap(defined_args, config, DEFAULT)
|
||||
>>> combined['verbosity']
|
||||
1
|
||||
|
||||
>>> args, _ = parser.parse_known_args(['-vv'])
|
||||
>>> defined_args = {k: v for k, v in vars(args).items() if v}
|
||||
>>> combined = collections.ChainMap(defined_args, config, DEFAULT)
|
||||
>>> combined['verbosity']
|
||||
2
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
>>> nodes = [
|
||||
... ('a', 'b'),
|
||||
... ('a', 'c'),
|
||||
... ('b', 'a'),
|
||||
... ('b', 'd'),
|
||||
... ('c', 'a'),
|
||||
... ('d', 'a'),
|
||||
... ('d', 'b'),
|
||||
... ('d', 'c'),
|
||||
... ]
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> graph = dict()
|
||||
>>> for from_, to in nodes:
|
||||
... if from_ not in graph:
|
||||
... graph[from_] = []
|
||||
... graph[from_].append(to)
|
||||
|
||||
>>> import pprint
|
||||
|
||||
>>> pprint.pprint(graph)
|
||||
{'a': ['b', 'c'],
|
||||
'b': ['a', 'd'],
|
||||
'c': ['a'],
|
||||
'd': ['a', 'b', 'c']}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> import collections
|
||||
|
||||
>>> graph = collections.defaultdict(list)
|
||||
>>> for from_, to in nodes:
|
||||
... graph[from_].append(to)
|
||||
|
||||
>>> import pprint
|
||||
|
||||
>>> pprint.pprint(graph)
|
||||
defaultdict(<class 'list'>,
|
||||
{'a': ['b', 'c'],
|
||||
'b': ['a', 'd'],
|
||||
'c': ['a'],
|
||||
'd': ['a', 'b', 'c']})
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> counter = collections.defaultdict(int)
|
||||
>>> counter['spam'] += 5
|
||||
>>> counter
|
||||
defaultdict(<class 'int'>, {'spam': 5})
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> import collections
|
||||
|
||||
>>> def tree(): return collections.defaultdict(tree)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> import json
|
||||
>>> import collections
|
||||
|
||||
|
||||
>>> def tree():
|
||||
... return collections.defaultdict(tree)
|
||||
|
||||
>>> colours = tree()
|
||||
>>> colours['other']['black'] = 0x000000
|
||||
>>> colours['other']['white'] = 0xFFFFFF
|
||||
>>> colours['primary']['red'] = 0xFF0000
|
||||
>>> colours['primary']['green'] = 0x00FF00
|
||||
>>> colours['primary']['blue'] = 0x0000FF
|
||||
>>> colours['secondary']['yellow'] = 0xFFFF00
|
||||
>>> colours['secondary']['aqua'] = 0x00FFFF
|
||||
>>> colours['secondary']['fuchsia'] = 0xFF00FF
|
||||
|
||||
>>> print(json.dumps(colours, sort_keys=True, indent=4))
|
||||
{
|
||||
"other": {
|
||||
"black": 0,
|
||||
"white": 16777215
|
||||
},
|
||||
"primary": {
|
||||
"blue": 255,
|
||||
"green": 65280,
|
||||
"red": 16711680
|
||||
},
|
||||
"secondary": {
|
||||
"aqua": 65535,
|
||||
"fuchsia": 16711935,
|
||||
"yellow": 16776960
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
>>> import enum
|
||||
|
||||
|
||||
>>> class Color(enum.Enum):
|
||||
... red = 1
|
||||
... green = 2
|
||||
... blue = 3
|
||||
|
||||
>>> Color.red
|
||||
<Color.red: 1>
|
||||
>>> Color['red']
|
||||
<Color.red: 1>
|
||||
>>> Color(1)
|
||||
<Color.red: 1>
|
||||
>>> Color.red.name
|
||||
'red'
|
||||
>>> Color.red.value
|
||||
1
|
||||
>>> isinstance(Color.red, Color)
|
||||
True
|
||||
>>> Color.red is Color['red']
|
||||
True
|
||||
>>> Color.red is Color(1)
|
||||
True
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> for color in Color:
|
||||
... color
|
||||
<Color.red: 1>
|
||||
<Color.green: 2>
|
||||
<Color.blue: 3>
|
||||
|
||||
>>> colors = dict()
|
||||
>>> colors[Color.green] = 0x00FF00
|
||||
>>> colors
|
||||
{<Color.green: 2>: 65280}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> import enum
|
||||
|
||||
|
||||
>>> class Spam(enum.Enum):
|
||||
... EGGS = 'eggs'
|
||||
|
||||
>>> Spam.EGGS == 'eggs'
|
||||
False
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> import enum
|
||||
|
||||
|
||||
>>> class Spam(str, enum.Enum):
|
||||
... EGGS = 'eggs'
|
||||
|
||||
>>> Spam.EGGS == 'eggs'
|
||||
True
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
>>> import heapq
|
||||
|
||||
|
||||
>>> heap = [1, 3, 5, 7, 2, 4, 3]
|
||||
>>> heapq.heapify(heap)
|
||||
>>> heap
|
||||
[1, 2, 3, 7, 3, 4, 5]
|
||||
|
||||
>>> while heap:
|
||||
... heapq.heappop(heap), heap
|
||||
(1, [2, 3, 3, 7, 5, 4])
|
||||
(2, [3, 3, 4, 7, 5])
|
||||
(3, [3, 5, 4, 7])
|
||||
(3, [4, 5, 7])
|
||||
(4, [5, 7])
|
||||
(5, [7])
|
||||
(7, [])
|
||||
|
||||
|
||||
>>> def heapsort(iterable):
|
||||
... heap = []
|
||||
... for value in iterable:
|
||||
... heapq.heappush(heap, value)
|
||||
...
|
||||
... while heap:
|
||||
... yield heapq.heappop(heap)
|
||||
>>> list(heapsort([1, 3, 5, 2, 4, 1]))
|
||||
[1, 1, 2, 3, 4, 5]
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
>>> import bisect
|
||||
|
||||
Using the regular sort:
|
||||
>>> sorted_list = []
|
||||
>>> sorted_list.append(5) # O(1)
|
||||
|
||||
>>> sorted_list.append(3) # O(1)
|
||||
|
||||
>>> sorted_list.append(1) # O(1)
|
||||
|
||||
>>> sorted_list.append(2) # O(1)
|
||||
|
||||
>>> sorted_list.sort() # O(n * log(n)) = 4 * log(4) = 8
|
||||
|
||||
>>> sorted_list
|
||||
[1, 2, 3, 5]
|
||||
|
||||
Using bisect:
|
||||
>>> sorted_list = []
|
||||
>>> bisect.insort(sorted_list, 5) # O(n) = 1
|
||||
|
||||
>>> bisect.insort(sorted_list, 3) # O(n) = 2
|
||||
|
||||
>>> bisect.insort(sorted_list, 1) # O(n) = 3
|
||||
|
||||
>>> bisect.insort(sorted_list, 2) # O(n) = 4
|
||||
|
||||
>>> sorted_list
|
||||
[1, 2, 3, 5]
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> sorted_list = [1, 2, 5]
|
||||
>>> def contains(sorted_list, value):
|
||||
... for item in sorted_list:
|
||||
... if item > value:
|
||||
... break
|
||||
... elif item == value:
|
||||
... return True
|
||||
... return False
|
||||
|
||||
>>> contains(sorted_list, 2) # Need to walk through 2 items, O(n) = 2
|
||||
True
|
||||
>>> contains(sorted_list, 4) # Need to walk through n items, O(n) = 3
|
||||
False
|
||||
>>> contains(sorted_list, 6) # Need to walk through n items, O(n) = 3
|
||||
False
|
||||
|
||||
|
||||
>>> import bisect
|
||||
|
||||
>>> sorted_list = [1, 2, 5]
|
||||
>>> def contains(sorted_list, value):
|
||||
... i = bisect.bisect_left(sorted_list, value)
|
||||
... return i < len(sorted_list) and sorted_list[i] == value
|
||||
|
||||
>>> contains(sorted_list, 2) # Found it the first step, O(log(n)) = 1
|
||||
True
|
||||
>>> contains(sorted_list, 4) # No result after 2 steps, O(log(n)) = 2
|
||||
False
|
||||
>>> contains(sorted_list, 6) # No result after 2 steps, O(log(n)) = 2
|
||||
False
|
||||
|
||||
|
||||
>>> import bisect
|
||||
>>> import collections
|
||||
|
||||
>>> class SortedList:
|
||||
... def __init__(self, *values):
|
||||
... self._list = sorted(values)
|
||||
...
|
||||
... def index(self, value):
|
||||
... i = bisect.bisect_left(self._list, value)
|
||||
... if i < len(self._list) and self._list[i] == value:
|
||||
... return index
|
||||
...
|
||||
... def delete(self, value):
|
||||
... del self._list[self.index(value)]
|
||||
...
|
||||
... def add(self, value):
|
||||
... bisect.insort(self._list, value)
|
||||
...
|
||||
... def __iter__(self):
|
||||
... for value in self._list:
|
||||
... yield value
|
||||
...
|
||||
... def __exists__(self, value):
|
||||
... return self.index(value) is not None
|
||||
|
||||
>>> sorted_list = SortedList(1, 3, 6, 2)
|
||||
>>> 3 in sorted_list
|
||||
True
|
||||
>>> 5 in sorted_list
|
||||
False
|
||||
>>> sorted_list.add(5)
|
||||
>>> 5 in sorted_list
|
||||
True
|
||||
>>> list(sorted_list)
|
||||
[1, 2, 3, 5, 6]
|
||||
@@ -0,0 +1,37 @@
|
||||
>>> class Borg:
|
||||
... _state = {}
|
||||
... def __init__(self):
|
||||
... self.__dict__ = self._state
|
||||
|
||||
>>> class SubBorg(Borg):
|
||||
... pass
|
||||
|
||||
>>> a = Borg()
|
||||
>>> b = Borg()
|
||||
>>> c = Borg()
|
||||
>>> a.a_property = 123
|
||||
>>> b.a_property
|
||||
123
|
||||
>>> c.a_property
|
||||
123
|
||||
|
||||
|
||||
>>> class Singleton:
|
||||
... def __new__(cls):
|
||||
... if not hasattr(cls, '_instance'):
|
||||
... cls._instance = super(Singleton, cls).__new__(cls)
|
||||
...
|
||||
... return cls._instance
|
||||
|
||||
>>> class SubSingleton(Singleton):
|
||||
... pass
|
||||
|
||||
|
||||
>>> a = Singleton()
|
||||
>>> b = Singleton()
|
||||
>>> c = SubSingleton()
|
||||
>>> a.a_property = 123
|
||||
>>> b.a_property
|
||||
123
|
||||
>>> c.a_property
|
||||
123
|
||||
@@ -0,0 +1,23 @@
|
||||
>>> class Sandwich:
|
||||
...
|
||||
... def __init__(self, spam):
|
||||
... self.spam = spam
|
||||
...
|
||||
... @property
|
||||
... def spam(self):
|
||||
... return self._spam
|
||||
...
|
||||
... @spam.setter
|
||||
... def spam(self, value):
|
||||
... self._spam = value
|
||||
... if self._spam >= 5:
|
||||
... print('You must be hungry')
|
||||
...
|
||||
... @spam.deleter
|
||||
... def spam(self):
|
||||
... self._spam = 0
|
||||
|
||||
>>> sandwich = Sandwich(2)
|
||||
>>> sandwich.spam += 1
|
||||
>>> sandwich.spam += 2
|
||||
You must be hungry
|
||||
@@ -0,0 +1,22 @@
|
||||
>>> a = dict(x=1, y=2)
|
||||
>>> b = dict(y=1, z=2)
|
||||
|
||||
>>> c = a.copy()
|
||||
>>> c
|
||||
{'x': 1, 'y': 2}
|
||||
>>> c.update(b)
|
||||
|
||||
>>> a
|
||||
{'x': 1, 'y': 2}
|
||||
>>> b
|
||||
{'y': 1, 'z': 2}
|
||||
>>> c
|
||||
{'x': 1, 'y': 1, 'z': 2}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> a = dict(x=1, y=2)
|
||||
>>> b = dict(y=1, z=2)
|
||||
|
||||
>>> a | b
|
||||
{'x': 1, 'y': 1, 'z': 2}
|
||||
Reference in New Issue
Block a user