Type Hinting: Default Parameters

How do I add default parameters to functions when using type hinting?

Your second way is correct.

def foo(opts: dict = {}):
pass

print(foo.__annotations__)

this outputs

{'opts': <class 'dict'>}

It's true that's it's not listed in PEP 484, but type hints are an application of function annotations, which are documented in PEP 3107. The syntax section makes it clear that keyword arguments works with function annotations in this way.

I strongly advise against using mutable keyword arguments. More information here.

Type Hinting: Default Parameters

You can't typehint strings, you can only typehint objects and arrays, so this is incorrect:

function setName ( string $name = "happ") {

(The reason you don't get a compile-time error here is because PHP is interpreting "string" as the name of a class.)

The wording in the docs means that if you do this:

function foo(Foo $arg) {

Then the argument passed to foo() must be an instance of object Foo. But if you do this:

function foo(Foo $arg = null) {

Then the argument passed to foo() can either be an instance of object Foo, or null. Note also that if you do this:

function foo(array $foo = array(1, 2, 3))

Then you can't call foo(null). If you want this functionality, you can do something like this:

function foo(array $foo = null) {
if ($foo === null) {
$foo = array(1, 2, 3);
}

[Edit 1] As of PHP 5.4, you can typehint callable:

function foo(callable $callback) {
call_user_func($callback);
}

[Edit 2] As of PHP 7.0, you can typehint bool, float, int, and string. This makes the code in the question valid syntax. As of PHP 7.1, you can typehint iterable.

How to type hint function with a callable argument and default value

You could use the @overload for correctly type hinting of function with default argument for your case:

from typing import Callable, List, TypeVar, overload, Set

T = TypeVar("T")

@overload
def transform(data: List[int]) -> Set[int]: ...

@overload
def transform(data: List[int], ret_type: Callable[[List[int]], T]) -> T: ...

# untyped implementation
def transform(data, ret_type = set):
return ret_type(data)

a = [1, 2, 3]
my_set: Set = transform(a)

How to type hint a Callable of a function with default arguments?

Define this:

class Foo(Protocol):
def __call__(self, x: int = ..., /) -> float:
...

then type hint foo as Foo instead of Callable[[int], float]. Callback protocols allow you to:

define flexible callback types that are hard (or even impossible) to express using the Callable[...] syntax

and optional arguments are one of those impossible things to express with a normal Callable. The / at the end of __call__'s signature makes x a positional-only parameter, which allows any passed function to bar to have a parameter name that is not x (your specific example of foo calls it arg instead). If you removed /, then not only would the types have to line up as expected, but the names would have to line up too because you would be implying that Foo could be called with a keyword argument. Because bar doesn't call foo with keyword arguments, opting into that behavior by omitting the / imposes inflexibility on the user of bar (and would make your current example still fail because "arg" != "x").

Type-hinting parameters with a sentinel value as the default

Something I like to do — which is only a slight variation on @Blckknght's answer — is to use a metaclass to give my sentinel class a nicer repr and make it always-falsey.


sentinel.py

from typing import Literal 

class SentinelMeta(type):
def __repr__(cls) -> str:
return f'<{cls.__name__}>'

def __bool__(cls) -> Literal[False]:
return False

class Sentinel(metaclass=SentinelMeta): pass

main.py

from sentinel import Sentinel

class DEFAULT(Sentinel): pass

You use it in type hints exactly in the same way @Blckknght suggests:

def spam(ham: list[str]|None|type[DEFAULT] = DEFAULT): ...

But you have the added advantages that your sentinel value is always falsey and has a nicer repr:

>>> DEFAULT
<DEFAULT>
>>> bool(DEFAULT)
False


Related Topics



Leave a reply



Submit