检查 Python 中的 function/method 中的参数类型
Check the type of the arguments in a function/method in Python
在 Python 中,我想检查传递给函数的参数类型。
我写了两个实现:
class FooFloat(float):
pass
# Solution 1
def foo(foo_instance):
if type(foo_instance) is FooFloat:
raise TypeError, 'foo only accept FooFloat input'
# Solution 2
def foo(foo_instance):
assert type(foo_instance) is FooFloat, 'foo only accept FooFloat input'
在我看来,后者更易于阅读且样板更少。但是它会抛出一个 AssertionError
这不是我想提出的错误类型。
在这种情况下是否有更好的第三种解决方案更常见?
我在考虑装饰器:
@argtype('foo_instance', FooFloat)
def foo(foo_instance):
pass
我喜欢这个想法并考虑在未来使用它。我实现的第三种解决方案如下,请试一试。
def argtype(arg_name, arg_type):
def wrap_func(func):
def wrap_args(*args, **kwargs):
if not isinstance(kwargs.get(arg_name), arg_type):
raise TypeError, '%s\'s argument %s should be %s type' % (func.__name__, arg_name, arg_type.__name__)
return func(*args, **kwargs)
return wrap_args
return wrap_func
@argtype('bar', int)
@argtype('foo', int)
def work(foo, bar):
print 'hello word'
work(foo='a', bar=1)
另外我觉得如果有继承的话用isinstance比较合适。
isinstance()
这样做。它接受类型和子类型。
if not isinstance(arg,<required type>):
raise TypeError("arg: expected `%s', got `%s'"%(<required type>,type(arg))
消除所有重复后(DRY原则),变成:
(n,t)=('arg',<required_type>);o=locals()[n]
if not isinstance(o,t):
raise TypeError("%(n)s: expected `%(t)s', got `%(rt)s'"
%dict(locals(),rt=type(o)) # fine in this particular case.
# See
# for other ways and limitations
del n,t,o
就个人而言,我会使用 assert
代替,除非我关心它抛出哪些异常(我通常不关心 - 无效参数是致命错误,所以我只对事实感兴趣被抛出):
assert isinstance(arg,<type>),"expected `%s',got `%s'"%(<type>,type(arg))
#arg name would be seen in the source in stacktrace
同时考虑 duck typing 而不是显式类型检查(这包括检查特殊成员,例如 __iter__
用于迭代)。完整的 "duck typing vs type checks" 讨论超出了当前主题的范围,但看起来显式检查更适合高度专业化的 and/or 复杂接口,而不是简单和通用的接口。
在 Python 中,我想检查传递给函数的参数类型。
我写了两个实现:
class FooFloat(float):
pass
# Solution 1
def foo(foo_instance):
if type(foo_instance) is FooFloat:
raise TypeError, 'foo only accept FooFloat input'
# Solution 2
def foo(foo_instance):
assert type(foo_instance) is FooFloat, 'foo only accept FooFloat input'
在我看来,后者更易于阅读且样板更少。但是它会抛出一个 AssertionError
这不是我想提出的错误类型。
在这种情况下是否有更好的第三种解决方案更常见?
我在考虑装饰器:
@argtype('foo_instance', FooFloat)
def foo(foo_instance):
pass
我喜欢这个想法并考虑在未来使用它。我实现的第三种解决方案如下,请试一试。
def argtype(arg_name, arg_type):
def wrap_func(func):
def wrap_args(*args, **kwargs):
if not isinstance(kwargs.get(arg_name), arg_type):
raise TypeError, '%s\'s argument %s should be %s type' % (func.__name__, arg_name, arg_type.__name__)
return func(*args, **kwargs)
return wrap_args
return wrap_func
@argtype('bar', int)
@argtype('foo', int)
def work(foo, bar):
print 'hello word'
work(foo='a', bar=1)
另外我觉得如果有继承的话用isinstance比较合适。
isinstance()
这样做。它接受类型和子类型。
if not isinstance(arg,<required type>):
raise TypeError("arg: expected `%s', got `%s'"%(<required type>,type(arg))
消除所有重复后(DRY原则),变成:
(n,t)=('arg',<required_type>);o=locals()[n]
if not isinstance(o,t):
raise TypeError("%(n)s: expected `%(t)s', got `%(rt)s'"
%dict(locals(),rt=type(o)) # fine in this particular case.
# See
# for other ways and limitations
del n,t,o
就个人而言,我会使用 assert
代替,除非我关心它抛出哪些异常(我通常不关心 - 无效参数是致命错误,所以我只对事实感兴趣被抛出):
assert isinstance(arg,<type>),"expected `%s',got `%s'"%(<type>,type(arg))
#arg name would be seen in the source in stacktrace
同时考虑 duck typing 而不是显式类型检查(这包括检查特殊成员,例如 __iter__
用于迭代)。完整的 "duck typing vs type checks" 讨论超出了当前主题的范围,但看起来显式检查更适合高度专业化的 and/or 复杂接口,而不是简单和通用的接口。