quick python - rFronteddu/general_wiki GitHub Wiki
List
List Comprehensions
Syntax
newlist = [expression for item in iterable if condition == True]
Fruits name that start with 'a'
fruits = ["apple", "orange", "banana", "ananas"]
a_fruits = [x for x in fruits if x.startswith("a") ]
Range of numbers
numbers = [x for x in range(10)]
Expression can be manipulated to apply to all outcome elements
fruits = ["apple", "orange", "banana"]
not_apple_upper_fruits = [x.upper() for x in fruits if x != "apple"]
Expression can be whatever - Ok for each element not apple
fruits = ["apple", "orange", "banana"]
not_apple_upper_fruits = ["ok" for x in fruits if x != "apple"]
Can also contain conditions to manipulate outcome
fruits = ["apple", "orange", "banana"]
not_apple_upper_fruits = [x if x != "banana" else "orange" for x in fruits if x != "apple"] => ["orange", "orange"]
Set
Set to list
l = list(map_set)
Map
Map for each
for k, v in x_map.items():
...
To access elements in order ...python for k, v in sorted(x_map.items()):
Get or default
```python
x_map.get(k, -1)
Given a map/dictionary whose values are lists, get all items in the list for key k starting at index start.
m = []
for index in range (start, len(log[k])):
m.append(log[k][index])
OR
m = log[k][start:]
Creates boilerplate for map
from collections import defaultdict
x = defaultdict[set]
Threading
import threading
...
class QNode(Node):
def __init__(
self,
...
):
super().__init__(...)
self.lock = threading.Lock()
self.gossip_t = threading.Thread(
target=self._periodic_gossip,
daemon=True,
)
...
def _periodic_gossip(self):
while(True):
time.sleep(1)
with self._lock()
def run(self):
super().run()
self.gossip_t.start()
Asyncio
Locks
import asyncio
lock = asyncio.Lock()
...
async with lock:
...
List of RPCs:
import asyncio
...
r_calls = []
r_calls.append(f) # f is an async def function
...
results = await asyncio.gather(*r_calls)
A loop that waits asynchronously
async def ticker():
while True:
print("tick")
await asyncio.sleep(1)
async def main():
await ticker()
asyncio.run(main())
Run multiple workers
import asyncio
async def worker(name):
while True:
print(f"{name} working")
await asyncio.sleep(1)
async def main():
await asyncio.gather(
worker("A"),
worker("B"),
worker("C"),
)
asyncio.run(main())
Blocking to concurrent:
tasks = [asyncio.create_task(fetch(url)) for url in urls]
results = await asyncio.gather(*tasks)
Blocking to asyncio
import asyncio
import time
def blocking_work():
time.sleep(2)
return "done"
async def main():
result = await asyncio.to_thread(blocking_work)
print(result)
asyncio.run(main())
Producer Consumer
import asyncio
async def producer(queue):
for i in range(5):
await queue.put(i)
print("produced", i)
await queue.put(None) # sentinel
async def consumer(queue):
while True:
item = await queue.get()
if item is None:
break
print("consumed", item)
queue.task_done()
async def main():
queue = asyncio.Queue()
await asyncio.gather(
producer(queue),
consumer(queue),
)
asyncio.run(main())
Prevent interleaving:
lock = asyncio.Lock()
counter = 0
async def increment():
global counter
async with lock:
old = counter
await asyncio.sleep(0) # simulate yield
counter = old + 1
Practical template
import asyncio
async def handle_item(item):
print("start", item)
await asyncio.sleep(1)
print("done", item)
return item * 2
async def main():
items = [1, 2, 3, 4, 5]
tasks = [
asyncio.create_task(handle_item(item))
for item in items
]
results = await asyncio.gather(*tasks)
print(results)
if __name__ == "__main__":
asyncio.run(main())
Practical template 2:
async def handle_message(msg):
...
async def receive_loop():
while True:
msg = await read_message()
asyncio.create_task(handle_message(msg))
Hash
Stable Hash:
import hashlib
def owner_for_key(key: str) -> str:
digest = hashlib.sha256(key.encode()).hexdigest()
value = int(digest, 16)
index = value % len(node.node_ids)
return node.node_ids[index]
Random
import random
d = random.uniform(min, max)
i = random.randint(min, max)
Random sample
import random
peers = ["n0", "n1", "n2", "n3", "n4", "n5"]
chosen = random.sample(peers, k=4)