Sure, it's just a specific kind of type-checking decorator in the same vein as the ones you can see at e.g. [0]. Obviously it can be made a lot more sophisticated to only pick up certain arguments. You can do a similar thing with metaclasses to prevent object attributes being set as None, too.
def isnotnone(fn):
def decorator(*args, **kwargs):
for arg in args:
if arg is None:
raise TypeError("{0} does not accept None".format(fn.func_name))
for arg in kwargs.values():
if arg is None:
raise TypeError("{0} does not accept None".format(fn.func_name))
return fn(*args,**kwargs)
return decorator
@isnotnone
def f(a, b=dict):
return a(), b()
>>> f(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in decorator
TypeError: f does not accept None
>>> f(b=None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in decorator
TypeError: f does not accept None
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in decorator
TypeError: f() takes at least 1 argument (0 given)
>>> f(str)
('', {})
>>>