我希望检查模块中每个函数的参数类型(不使用inspect模块)。 我自己做的最简单的解决方案是分别对每个函数进行检查。
def func1( num1, num2 ): # the two params must be integers
if isinstance( num1, int ) and isinstance( num2, int ):
# ...function code...
pass
else:
return
def func2( float1 ): # The only param must be float
if isinstance( float1, float ):
# ...function code...
pass
else:
return
def func3( str1 ): # string
if isinstance( str1, str ):
# ...function code...
print 'fdfd'
pass
else:
return
# and, so on ...
但是,想要在模块级别进行,而不是为每个函数执行此操作。每个函数可以有不同的参数。请注意,这不是函数重载。我在想写一个装饰者或一个元类。以下是我在这两种方法中遇到的问题: -
def dec( funcName ): def typeChecker(): i = __import__( __name__ ) for m in map( lambda x: i.__getattribute__( x ), dir( i ) ): if '__call__' in dir( m ): #Identifying a real function or callable which can be treated as function ## Now, that the function is identified, what should I do here to type-check the arguments?? return typeChecker
请在此提供一些见解,了解我如何才能完成这项工作。
2.使用元类创建功能
我只是想知道我是否可以使用元类访问发送给函数的参数,然后验证每个参数,然后返回一个全新的类,负责创建函数对象。但是,不知道该怎么做。这是解决这个问题的好方法吗?
Martijn Peters给出了一个非常好的建议 - 使用注释。我们可以使用Python 2.7中的某些东西吗?
答案 0 :(得分:1)
通过装饰器这样做很容易 - 在Python 2中,您必须明确地装饰每个函数以注释类型 每个参数 - 或者你可以在doc-string上使用一些标记来使用一些注释, 并在模块的底部发出一个调用,它将迭代所有 模块上的对象,并将装饰器应用于每个函数 其中定义。
在这两种情况下,像这样的装饰者就足够了:
from functools import wraps
from itertools import count
def typechecker(*types, **kw_types):
def decorator(func):
@wraps(func)
def wrapper(*args, **kw):
for position, type_, arg in zip(count(), types, args):
if not isinstance(arg, type_):
raise TypeError("Argument in position %s should be a %s"
% (position, type_))
for key, type_ in kw_types.items():
if key in kw_types and not isinstance(kw[key], type_):
raise TypeError("Argument %s should be a %s"
% (key, type_))
return func(*args, **kw)
return wrapper
return decorator
你可以看到它的工作原理如下:
>>> @typechecker(int, int)
... def mysum(a,b):
... return a + b
...
>>> mysum(2,3)
5
>>> mysum(2.0,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in wrapper
TypeError: Argument in position 0 should be a <type 'int'>
>>>
答案 1 :(得分:-1)
我的倾向是这样的:
class A(object):
def func(self, arg):
result = self._get_func(arg)(arg)
def _get_func(self, arg):
# Create and return the appropriate function here.
# You have a variety of options, e.g. arg.__class__ (if it exists),
# or use a bunch of isinstance checks, etc.
# Please bear in mind that this is really unpythonic!!
if isinstance(arg, basestring):
pass
如果您要调用该函数很多,这显然效率低下,因此您需要缓存特定的函数,并尝试首先从_get_func
内的缓存中提取。
def _get_func(self, arg):
if arg.__class__ in self._cache: # Or whatever
return self._cache[arg.__class__]
else:
pass # Create and return the appropriate function here.
当然你可以根据需要覆盖_get_func
方法(这应该在模块级或类级别工作,尽管为了清晰起见我可能更喜欢类。)
另外值得一提的是,这真的是单声道的。如果他们需要做不同的事情而不是将它们隐藏在函数构造函数中,那么在open中编写单独的函数通常会更加清晰。或者至少“更好地请求宽恕”并使用try
/ except
块来封装仅适用于特定类型/类的操作。