From 5199d9fcc31dce17244154749aa88c9c2189d273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Riegel?= <96702577+LoicRiegel@users.noreply.github.com> Date: Thu, 31 Oct 2024 01:49:43 +0100 Subject: [PATCH] Improve challenges with alternative solutions and hints (#125) * Add alternative solution in advanced-forward challenge "from __future__ import annotations" * Improve extreme-self-casting challenge * Improve advanced-variadic-generics challenge --- challenges/advanced-forward/solution.py | 13 +++++++ .../advanced-variadic-generics/hints.md | 1 + .../advanced-variadic-generics/solution.py | 16 ++++---- .../advanced-variadic-generics/solution2.py | 23 ----------- challenges/extreme-self-casting/hints.md | 1 + challenges/extreme-self-casting/solution.py | 25 ++++++++---- challenges/extreme-self-casting/solution2.py | 39 ------------------- 7 files changed, 41 insertions(+), 77 deletions(-) create mode 100644 challenges/advanced-variadic-generics/hints.md delete mode 100644 challenges/advanced-variadic-generics/solution2.py create mode 100644 challenges/extreme-self-casting/hints.md delete mode 100644 challenges/extreme-self-casting/solution2.py diff --git a/challenges/advanced-forward/solution.py b/challenges/advanced-forward/solution.py index e32ff36..6995bdd 100644 --- a/challenges/advanced-forward/solution.py +++ b/challenges/advanced-forward/solution.py @@ -8,6 +8,19 @@ def copy(self) -> "MyClass": return copied_object +# Alternative soltion: +# +# from __future__ import annotations +# class MyClass: +# def __init__(self, x: int) -> None: +# self.x = x +# +# # TODO: Fix the type hints of `copy` to make it type check +# def copy(self) -> MyClass: +# copied_object = MyClass(x=self.x) +# return copied_object + + ## End of your code ## from typing import assert_type diff --git a/challenges/advanced-variadic-generics/hints.md b/challenges/advanced-variadic-generics/hints.md new file mode 100644 index 0000000..b37e414 --- /dev/null +++ b/challenges/advanced-variadic-generics/hints.md @@ -0,0 +1 @@ +Check out [TypeVarTuple](https://docs.python.org/3/library/typing.html#typing.TypeVarTuple). diff --git a/challenges/advanced-variadic-generics/solution.py b/challenges/advanced-variadic-generics/solution.py index b2fbca5..151e270 100644 --- a/challenges/advanced-variadic-generics/solution.py +++ b/challenges/advanced-variadic-generics/solution.py @@ -4,13 +4,15 @@ Define an `Array` type that supports element-wise addition of arrays with identical dimensions and types. """ -from typing import Generic, TypeVar, TypeVarTuple, assert_type - -T = TypeVar("T") -Ts = TypeVarTuple("Ts") - - -class Array(Generic[*Ts]): +# For Python < 3.12 +# Ts = TypeVarTuple("Ts") +# +# class Array(Generic[*Ts]): +# def __add__(self, other: "Array[*Ts]") -> "Array[*Ts]": +# ... + +# For Python >= 3.12 +class Array[*Ts]: def __add__(self, other: "Array[*Ts]") -> "Array[*Ts]": ... diff --git a/challenges/advanced-variadic-generics/solution2.py b/challenges/advanced-variadic-generics/solution2.py deleted file mode 100644 index 2d08ea4..0000000 --- a/challenges/advanced-variadic-generics/solution2.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -TODO: - -Define an `Array` type that supports element-wise addition of arrays with identical dimensions and types. -""" - -from typing import assert_type - - -class Array[*Ts]: - def __add__(self, other: "Array[*Ts]") -> "Array[*Ts]": - ... - - -## End of your code ## -from typing import assert_type - -a: Array[float, int] = Array() -b: Array[float, int] = Array() -assert_type(a + b, Array[float, int]) - -c: Array[float, int, str] = Array() -assert_type(a + c, Array[float, int, str]) # expect-type-error diff --git a/challenges/extreme-self-casting/hints.md b/challenges/extreme-self-casting/hints.md new file mode 100644 index 0000000..3011cca --- /dev/null +++ b/challenges/extreme-self-casting/hints.md @@ -0,0 +1 @@ +Checkout [ParamSpec](https://docs.python.org/3/library/typing.html#typing.ParamSpec) and [Concatenate](https://docs.python.org/3/library/typing.html#typing.Concatenate). diff --git a/challenges/extreme-self-casting/solution.py b/challenges/extreme-self-casting/solution.py index 93822ba..f45ac09 100644 --- a/challenges/extreme-self-casting/solution.py +++ b/challenges/extreme-self-casting/solution.py @@ -12,16 +12,25 @@ from typing import Callable, Concatenate, Generic, ParamSpec, TypeVar - -R = TypeVar("R") -P = ParamSpec("P") - - -class Fn(Generic[R, P]): - def __init__(self, f: Callable[P, R]): +# # For Python < 3.12 +# R = TypeVar("R") +# P = ParamSpec("P") +# +# +# class Fn(Generic[R, P]): +# def __init__(self, f: Callable[P, R]): +# self.f = f +# +# def transform_callable(self) -> Callable[Concatenate[object, P], R]: +# ... + + +# For Python >= 3.12 +class Fn[R, **P]: + def __init__(self, f: Callable[P, R]) -> None: self.f = f - def transform_callable(self) -> Callable[Concatenate[object, P], R]: + def transform_callable(self) -> Callable[Concatenate[Any, P], R]: ... diff --git a/challenges/extreme-self-casting/solution2.py b/challenges/extreme-self-casting/solution2.py deleted file mode 100644 index 4c55776..0000000 --- a/challenges/extreme-self-casting/solution2.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -TODO: - -Fn is a class decorator which takes a callable (`f`). -Fn has a `transform_callable` method, which transform `f` into a different callable, -with an additional Any parameter at the beginning, while preserving the remaining parts -of the function signature. - -Note: you're only requried to add type annotations without implementing transform_callable. -""" - - -from typing import Callable, Concatenate, Any - - -class Fn[R, **P]: - def __init__(self, f: Callable[P, R]) -> None: - self.f = f - - def transform_callable(self) -> Callable[Concatenate[Any, P], R]: - ... - - -## End of your code ## -from typing import assert_type, Any - - -@Fn -def example(a: int, b: str, c: float, *, d: bool = False) -> None: - return - - -assert_type(example.f(1, "1", 1.0, d=False), None) - -a: Any = 11111111 -b = example.transform_callable()(a, 1, "1", 1.0, d=False) -assert_type(b, None) - -example.transform_callable()(1, "1", 1.0, d=False) # expect-type-error