*args and **kwargs?

How To Use args and kwargs in Python 3 by Lisa Tagliaferri, 20 November 2017.

>>> def hello(*args, **kwargs):
...     gretting = kwargs.pop('gretting', 'Hello')
...
...     print(f"""{gretting} {' '.join(args)}!""")
...
>>>
>>> hello("Laura", "Dang", gretting="Hi")
Hi Laura Dang!

Bare asterisk (*) in function argument

In Python 3 you can specify * in the argument list, from the Python 3.5 Documentation:

”Parameters after * or *identifier are keyword-only parameters and may only be passed used keyword arguments.”

>>> def is_birthday(*, birthday):
...     today = datetime.date.today()
...     if birthday.month == today.month and birthday.day == today.day:
...         print(f"Yes it's their birthday.")
...     else:
...         print(f"No it's not their birthday.")
...
>>>
>>> is_birthday(datetime.date(1986, 9, 19))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: is_birthday() takes exactly 1 positional argument (1 given)
>>>
>>> is_birthday(birthday=datetime.date(1986, 9, 19))
No it's not their birthday.
>>>

Forced naming of parameters in Python by Eli Bendersky, 12 January 2013.

Coerce to NamedTuple

from typing import Any, Dict, NamedTuple, Type
 
 
class AlbumTuple(NamedTuple):
    """Album Tuple Class."""
    name: str
    artist: str
    length: float
 
 
def coerce_to_namedtuple(d: Dict[str, Any], T: Type):
    """Create a NamedTuple from a dict, ignoring extra keys in the dict"""
    return T(**{k: v for k, v in d.items() if k in T._fields})
 
 
album = dict(name="Liar", artist="Fake Shark - Real Zombie!", length=47.15)
print(coerce_to_namedtuple(d, AlbumTuple))
# output: AlbumTuple(name="Liar", artist="Fake Shark - Real Zombie!", length=47.15)

coerce_to_namedtuple.py by Andy Mitchhank