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)