Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用单个接口验证不同函数的参数类型(不使用inspect)_Python_Types_Metaclass_Inspect - Fatal编程技术网

Python 使用单个接口验证不同函数的参数类型(不使用inspect)

Python 使用单个接口验证不同函数的参数类型(不使用inspect),python,types,metaclass,inspect,Python,Types,Metaclass,Inspect,我希望检查模块中每个函数的参数类型(不使用inspect模块)。 我自己做过的最简单的解决方案是分别在每个函数中实现检查 def func1( num1, num2 ): # the two params must be integers if isinstance( num1, int ) and isinstance( num2, int ): # ...function code... pass else: return

我希望检查模块中每个函数的参数类型(不使用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 ...
但是,我们希望在模块级别执行此操作,而不是针对每个功能执行此操作。每个函数可以有不同的参数。请注意,这不是函数重载。我想要么写一个装饰器,要么写一个元类。以下是我在这两种方法中面临的问题:-

  • 对所有函数使用公共装饰器:
    在这种方法中,我无法访问每个函数中定义的实际变量,因此放弃了这种想法。下面是我计划写的一个闭包(用作装饰器):
  • 请在这里提供一些见解,以了解我如何才能做到这一点

    2.使用元类创建函数
    我只是想知道是否可以使用元类访问发送给函数的参数,然后验证每个参数,然后返回一个全新的类,该类将负责创建函数对象。但是,我不知道怎么做。这是解决这个问题的好办法吗


    Martijn Peters给出了一个非常好的建议——使用注释。Python 2.7中是否有我们可以使用的东西?

    我倾向于这样:

    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
    
    >>> @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'>
    >>> 
    
    如果要频繁调用函数,这显然是效率低下的,因此您需要缓存特定的函数,并尝试在
    \u get\u 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.
    
    当然,您可以根据需要重写
    \u get\u func
    方法(这应该在模块级或类级工作,不过为了清晰起见,我可能更喜欢类)


    同样值得一提的是,这真的是不和谐的。如果函数需要做不同的事情,只需在开放的环境中编写单独的函数,而不是将它们隐藏在函数构造函数中,通常会更简洁。或者至少,“最好请求原谅”,并使用
    尝试
    /
    ,除了
    块来封装只适用于特定类型/类的操作。

    通过装饰器来实现这一点相当容易- 在Python2中,您必须显式地修饰每个函数,以注释其类型 每个参数-或者您可以使用文档字符串上的一些标记使用一些注释, 并在模块的底部放置一个调用,该调用将遍历所有 对象,并将装饰器应用于每个函数 定义如下

    在这两种情况下,像这样的装饰师就足够了:

    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
    
    你可以看到它是这样工作的:

    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
    
    >>> @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'>
    >>> 
    
    >@typechecker(int,int)
    ... 定义mysum(a,b):
    ...    返回a+b
    ... 
    >>>糠秕(2,3)
    5.
    >>>迈苏姆(2.0,3)
    回溯(最近一次呼叫最后一次):
    文件“”,第1行,在
    包装器中第8行的文件“”
    TypeError:位置0中的参数应为
    >>> 
    
    您能解释一下我们如何在这里验证/键入检查每个参数吗?我不明白这个参数是如何与装饰程序对立的。您可以访问修饰函数的参数,但不能访问内部变量。那么,你知道什么?函数的参数或局部变量?是。没错。我最初认为我可以访问内部参数。但是,我错了。所以,我很快把注意力转移到了元类上。我不会用元类。尽量避免使用“魔法”。你考虑过依赖注射吗?不,我是新手。你能解释一下吗。没有一种方法可以实现所有功能。我问这个问题的原因是模块中有很多函数为什么需要访问函数的局部变量来检查其参数的类型?装饰师是进行此检查的常用方法