Python装饰器确保kwargs是正确的

时间:2009-09-18 20:01:57

标签: python

我做过一个装饰器,用于确保传递给构造函数的关键字参数是正确/预期的。代码如下:

from functools import wraps

def keyargs_check(keywords):
"""
This decorator ensures that the keys passed in kwargs are the onces that
are specified in the passed tuple. When applied this decorate will
check the keywords and will throw an exception if the developer used
one that is not recognized.

@type keywords: tuple
@param keywords: A tuple with all the keywords recognized by the function.
"""

def wrap(f):
    @wraps(f)
    def newFunction(*args, **kw):
        # we are going to add an extra check in kw
        for current_key in kw.keys():
            if not current_key in keywords:
                raise ValueError(
                    "The key {0} is a not recognized parameters by {1}.".format(
                        current_key, f.__name__))
        return f(*args, **kw)
    return newFunction
return wrap

from functools import wraps def keyargs_check(keywords): """ This decorator ensures that the keys passed in kwargs are the onces that are specified in the passed tuple. When applied this decorate will check the keywords and will throw an exception if the developer used one that is not recognized. @type keywords: tuple @param keywords: A tuple with all the keywords recognized by the function. """ def wrap(f): @wraps(f) def newFunction(*args, **kw): # we are going to add an extra check in kw for current_key in kw.keys(): if not current_key in keywords: raise ValueError( "The key {0} is a not recognized parameters by {1}.".format( current_key, f.__name__)) return f(*args, **kw) return newFunction return wrap 这个装饰器的一个示例用法如下:

class Person(object):

@keyargs_check(("name", "surname", "age"))
def __init__(self, **kwargs):
    # perform init according to args
如果开发人员传递了一个像“blah”这样的键,那么使用上面的代码将抛出异常。不幸的是,如果我定义以下内容,我的实现有一个主要的继承问题: class Person(object): @keyargs_check(("name", "surname", "age")) def __init__(self, **kwargs): # perform init according to args

因为我将kwargs传递给超类init方法,所以我会得到一个例外,因为“test”不在元组中传递给超类的装饰器。有没有办法让超级类中的装饰器知道额外的关键字?或事件更好,有没有一种标准的方法来实现我想要的目标?

更新:当开发人员传递错误的kwarg而不是我使用kwargs而不是args时,我更感兴趣的是自动化抛出异常的方式。我的意思是,我不想编写检查传递给每个类中的方法的args的代码。

1 个答案:

答案 0 :(得分:4)

你的装饰师没有必要。使用标准语法无法完成装饰器所做的唯一事情是阻止关键字args吸收位置参数。因此

class Base(object):
    def __init__(name=None,surname=None,age=None):
        #some code

class Child(Base):
    def __init__(test=None,**kwargs):
        Base.__init__(self,**kwargs)

这样做的好处是kwargs中的Child不会包含test。问题是你可以通过c = Child('red herring')这样的调用来解决问题。这是fixed in python 3.0

你的方法的问题在于你正在尝试使用装饰器来完成一个宏的工作,这是unpythonic。唯一可以帮助您获得所需内容的是修改代码中最内层函数(f的局部变量,特别是kwargs变量)的内容。你的装饰者应该如何知道包装器的内部,它如何知道它调用超类?