Created
February 2, 2025 11:57
-
-
Save mahenzon/693b70c665674854f87f1a31e96e9d14 to your computer and use it in GitHub Desktop.
Protocol annotation in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Protocol | |
class MessageCallback(Protocol): | |
__name__: str | |
def __call__( | |
self, | |
message: str, | |
size: int, | |
) -> None: ... | |
def process_incoming_message( | |
data: bytes, | |
callback: MessageCallback, | |
) -> None: | |
message = data.decode("utf-8") | |
message_size = len(message) | |
print("Notify callback", callback.__name__) | |
callback( | |
message, | |
message_size, | |
) | |
callback( | |
message=message, | |
size=message_size, | |
) | |
callback( | |
message, | |
size=message_size, | |
) | |
def my_callback( | |
message: str, | |
size: int, | |
extra: dict[str, str] | None = None, | |
) -> None: | |
print("received", repr(message), "of size", size) | |
def main() -> None: | |
data = b"Hello World!" | |
process_incoming_message( | |
data=data, | |
callback=my_callback, | |
) | |
if __name__ == "__main__": | |
main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Protocol | |
FILE_PATH = "/Users/suren/MyFiles/suren/videos/062.protocol-type/my-file.txt" | |
class Readable(Protocol): | |
def read(self) -> bytes: ... | |
class FileReader: | |
def __init__(self, filename: str) -> None: | |
self.filename = filename | |
def read(self) -> bytes: | |
""" | |
Вычитываем файл и возвращаем содержимое файла | |
""" | |
print("read data from filereader", self.filename) | |
# просто какие-то байты | |
return self.filename.encode() | |
class APIReader(Readable): | |
def __init__(self, api_path: str) -> None: | |
self.api_path = api_path | |
def read(self) -> bytes: | |
""" | |
Делаем API запрос и возвращаем байты | |
""" | |
print("read data from API", self.api_path) | |
# имитация | |
return self.api_path.encode() | |
def read_and_save_to_db(readable: Readable) -> None: | |
print("+ save to db:", readable.read()) | |
def main() -> None: | |
file_reader = FileReader("example-file.txt") | |
api_reader = APIReader("example/api/path") | |
# print(file_reader.read()) | |
# print(api_reader.read()) | |
read_and_save_to_db(file_reader) | |
read_and_save_to_db(api_reader) | |
print() | |
file = open(FILE_PATH, "rb") | |
read_and_save_to_db(file) | |
# reveal_type(file.read) | |
if __name__ == "__main__": | |
main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
from typing import Protocol, runtime_checkable | |
@runtime_checkable | |
class Shape(Protocol): | |
def area(self) -> float: ... | |
def perimeter(self) -> str: ... | |
class Circle: | |
def __init__(self, radius: float) -> None: | |
self.radius = radius | |
self.family = "circle" | |
def area(self) -> float: | |
return math.pi * self.radius**2 | |
def perimeter(self) -> float: | |
return 2 * math.pi * self.radius | |
circumference = perimeter | |
class Rectangle: | |
def __init__(self, width: float, height: float) -> None: | |
self.width = width | |
self.height = height | |
def area(self) -> float: | |
return self.width * self.height | |
def perimeter(self) -> float: | |
return 2 * (self.width + self.height) | |
def print_shape_info(shape: Shape) -> None: | |
print("Shape area", shape.area()) | |
print("Shape perimeter()", shape.perimeter()) | |
def main() -> None: | |
circle = Circle(5) | |
print("Circle perimeter", circle.perimeter()) | |
print("Circle circumference", circle.circumference()) | |
rectangle = Rectangle(5, 7) | |
# print_shape_info(circle) | |
# print_shape_info(rectangle) | |
for elem in [circle, rectangle, "foobar"]: | |
if isinstance(elem, Shape): | |
print(f"{elem.__class__.__name__} is a Shape") | |
print_shape_info(elem) | |
else: | |
print(f"Element type {type(elem)} is not a Shape") | |
if __name__ == "__main__": | |
main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[tool.mypy] | |
strict = true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment