预计阅读本页时间:-
Other Applications: Type Testing (If You Insist!)
The coding pattern we’ve arrived at for processing arguments in decorators could be applied in other contexts. Checking argument data types at development time, for example, is a straightforward extension:
def typetest(**argchecks):
def onDecorator(func):
....
def onCall(*pargs, **kargs):
positionals = list(allargs)[:len(pargs)]
for (argname, type) in argchecks.items():
if argname in kargs:
if not isinstance(kargs[argname], type):
...
raise TypeError(errmsg)
elif argname in positionals:
position = positionals.index(argname)
if not isinstance(pargs[position], type):
...
raise TypeError(errmsg)
else:
# Assume not passed: default
return func(*pargs, **kargs)
return onCall
return onDecorator
@typetest(a=int, c=float)
def func(a, b, c, d): # func = typetest(...)(func)
...
func(1, 2, 3.0, 4) # Okay
func('spam', 2, 99, 4) # Triggers exception correctly
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
In fact, we might even generalize further by passing in a test function, much as we did to add Public decorations earlier; a single copy of this sort of code would suffice for both range and type testing. Using function annotations instead of decorator arguments for such a decorator, as described in the prior section, would make this look even more like type declarations in other languages:
@typetest
def func(a: int, b, c: float, d): # func = typetest(func)
... # Gasp!...
As you should have learned in this book, though, this particular role is generally a bad idea in working code, and not at all Pythonic (in fact, it’s often a symptom of an ex-C++ programmer’s first attempts to use Python).
Type testing restricts your function to work on specific types only, instead of allowing it to operate on any types with compatible interfaces. In effect, it limits your code and breaks its flexibility. On the other hand, every rule has exceptions; type checking may come in handy in isolated cases while debugging and when interfacing with code written in more restrictive languages, such as C++. This general pattern of argument processing might also be applicable in a variety of less controversial roles.