Skip to content

Instantly share code, notes, and snippets.

@Hugovdberg
Created January 28, 2023 10:37
Show Gist options
  • Save Hugovdberg/98e42f07b03c6f6bfc07e139bac2af8a to your computer and use it in GitHub Desktop.
Save Hugovdberg/98e42f07b03c6f6bfc07e139bac2af8a to your computer and use it in GitHub Desktop.
Positional only argument to prevent argument name clashes
from typing import Callable, Any, ParamSpec, TypeVar
a = TypeVar("a")
b = TypeVar("b")
c = TypeVar("c")
P = ParamSpec("P")
def delay_call(
func: Callable[P, a], *args: P.args, **kwargs: P.kwargs
) -> Callable[[], a]:
def wrapper() -> a:
return func(*args, **kwargs)
return wrapper
def delay_call2(
func: Callable[P, a], /, *args: P.args, **kwargs: P.kwargs
) -> Callable[[], a]:
def wrapper() -> a:
return func(*args, **kwargs)
return wrapper
def apply(func: Callable[[a, b], c], x: a, y: b) -> c:
return func(x, y)
def add(x: int, y: int) -> int:
return x + y
# Apply the add function to 1 and 2 works as expected
print("Direct call to apply", apply(add, 1, 2))
# Delaying the call to add works as expected
callable = delay_call(add, x=1, y=2)
print("Delayed call to add", callable())
# Delaying the call to apply does not work as expected because the func argument
# is both an argument to delay_call as well as an argument to apply.
try:
callable = delay_call(apply, func=add, x=1, y=2)
except TypeError as e:
print(f"{type(e).__name__}: {e}")
# Delaying the call to apply works as expected when making func a positional only
# argument, as func as a keyword argument is now part of the **kwargs.
callable = delay_call2(apply, func=add, x=1, y=2)
print("Delayed call to apply", callable())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment