Skip to content

Commit

Permalink
Framework design
Browse files Browse the repository at this point in the history
  • Loading branch information
you-n-g committed Jun 20, 2024
1 parent 0ad04b2 commit 3334ba9
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
5 changes: 5 additions & 0 deletions language/python/design/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Introduction

Python的各种设计模式
- 用linting辅助检测具体设计

65 changes: 65 additions & 0 deletions language/python/design/annot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# annotations


from typing import List, Sequence, Protocol


class IA: pass
class IB(IA): pass

class P(Protocol):
def h(self) -> List[IA]: ...


class A:
def f(self) -> List[IA]:
return [IA()]

def g(self) -> Sequence[IA]:
return [IA()]

def h(self) -> List[IA]:
return [IA()]


class B(A):
def f(self) -> List[IB]:
# NOTE: it is a invalid override in linting.
return [IB()]

def g(self) -> Sequence[IB]:
# NOTE: it is a valid overriding
return [IB()]

def h(self) -> List[IB]:
# NOTE: it is a invalid override in linting.
# So protocal does not help here
return [IB()]


# generic

from typing import Generic, TypeVar, List
# Define a type variable
T = TypeVar('T')
class Stack(Generic[T]):
def __init__(self):
self._items: List[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
def is_empty(self) -> bool:
return len(self._items) == 0
# Usage
int_stack = Stack[int]()
int_stack.push(1)
int_stack.push(2.) # NOTE: it is runnable but does not confirm with linting rules.
print(int_stack.pop()) # Output: 2.0
print(int_stack.pop()) # Output: 1

int_stack = Stack()
int_stack.push(1)
int_stack.push(2.)
print(int_stack.pop()) # Output: 2.0
print(int_stack.pop()) # Output: 1
40 changes: 40 additions & 0 deletions language/python/design/core_frame.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""
# We'll check the design with `ruff check` & `mypy`
"""
from typing import Generic, TypeVar

ASpecificBaseTask = TypeVar("ASpecificBaseTask", bound="BaseTask")
# Define a type, that refer to a more specific subclass than general `BaseTask`


# Core Framework
class BaseTask:
...


class BaseSolver(Generic[ASpecificBaseTask]):
"""
From a semantic perspective,
It defines a framework. But it is not designed to handle general BaseTask.
Instead, it is designed to handle a specific subclass of BaseTask (But all kinds of specific subclasses can be handled in this class).
"""

def g(self, a: ASpecificBaseTask) -> ASpecificBaseTask:
return a


# concrete framework
class MTask(BaseTask):
...


class MSolver(BaseSolver[MTask]):

def g(self, a: MTask) -> MTask:
"""`MSolver.g` only works when a is MTask"""
return a


ms = MSolver()
print(isinstance(ms, BaseSolver)) # it will not affect the type checking

0 comments on commit 3334ba9

Please sign in to comment.