Skip to content

Instantly share code, notes, and snippets.

@mahenzon
Created December 22, 2024 08:19
Show Gist options
  • Save mahenzon/99c9ed92cc3f7f63aaa7dad34791f598 to your computer and use it in GitHub Desktop.
Save mahenzon/99c9ed92cc3f7f63aaa7dad34791f598 to your computer and use it in GitHub Desktop.
Self type annotation in Python
[tool.mypy]
strict = true
mypy==1.13.0
mypy-extensions==1.0.0
typing_extensions==4.12.2
from typing import reveal_type, Any
from typing import Self
from typing import Sequence
class Stack[T]:
def __init__(self, values: Sequence[T] = ()) -> None:
self.values = list(values)
def push(self, value: T) -> Self:
self.values.append(value)
return self
def pop(self) -> T:
return self.values.pop()
def top(self) -> T:
return self.values[-1]
def is_empty(self) -> bool:
return not self.values
def __bool__(self) -> bool:
return not self.is_empty()
def copy(self) -> Self:
return self.__class__(self.values)
@classmethod
def from_dict_values(cls, values: dict[Any, T]) -> Self:
return cls(tuple(values.values()))
class IntStack(Stack[int]):
pass
def main() -> None:
# int_stack = Stack([1, 2, 3])
int_stack = Stack[int]()
int_stack.push(1)
int_stack.push(2)
int_stack.push(3)
val = int_stack.push(4).push(5).push(6).push(7).pop()
print(val)
nums_stack = int_stack.copy()
reveal_type(nums_stack)
while int_stack:
print(int_stack.pop())
print()
print("nums stack values:", nums_stack.values)
print(" int stack values:", int_stack.values)
print()
fruits = Stack(("apple", "banana", "cherry"))
fruits.push("orange").push("kiwi")
while fruits:
print(fruits.pop())
numbers_stack = IntStack()
numbers_stack.push(1).push(2).push(3).push(4).push(5).push(6)
another_numbers_stack = numbers_stack.copy()
reveal_type(another_numbers_stack)
# numbers_names = Stack[str].from_dict_values({1: "one", 2: "two", 3: "three", 4: "four", 5: "five"})
# numbers_names: Stack[str] = Stack.from_dict_values(
numbers_names = Stack.from_dict_values(
{1: "one", 2: "two", 3: "three", 4: "four", 5: "five"}
)
reveal_type(numbers_names)
numbers_names.push("six")
while numbers_names:
num_name = numbers_names.pop()
# reveal_type(num_name)
print(num_name)
if __name__ == "__main__":
main()
from typing import reveal_type, Self
class Line:
other: "Self | None" = None
@classmethod
def make_pair(cls: type[Self]) -> tuple[Self, Self]:
left = cls()
right = cls()
left.other = right
right.other = left
return left, right
class FizzLine(Line):
def fizz(self) -> str:
return f"Other fizz: {self.other}"
def main() -> None:
left_line, right_line = Line.make_pair()
reveal_type(left_line)
reveal_type(right_line)
f_left_line, f_right_line = FizzLine.make_pair()
reveal_type(f_left_line)
reveal_type(f_right_line)
reveal_type(f_left_line.other)
print(f_left_line.fizz())
print(f_left_line.other and f_left_line.other.fizz())
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment