更优雅地处理未定义的参数

时间:2012-03-25 18:46:10

标签: python

处理可变默认参数的公认范式是:

def func(self, a = None):
    if a is None:
        a = <some_initialisation>
    self.a = a

由于我可能不得不为几个参数做这个,我需要一遍又一遍地写出非常相似的3行。在初始化类对象或函数时,我发现很多文本都是非常标准的事情。

是不是有一个优雅的单行代替那些处理潜在未定义参数的3行和标准需要复制到类实例变量?

4 个答案:

答案 0 :(得分:4)

如果“falsy”值(0,空字符串,列表,字典等)不是a的有效值,则可以将初始化减少到一行:

a = a or <initialize_object>

答案 1 :(得分:3)

另一种做同样事情的方法如下:

def func(self,**kwargs):
    self.a=kwargs.get('a',<a_initialization>)
    ...

这有一个额外的好处,即传递给函数的值可以是None,初始化不会覆盖它。缺点是使用内置帮助功能的用户将无法告知您的函数正在寻找哪些关键字,除非您在docstring中明确拼写出来。

修改

另一条评论。用户可以使用未从kwargs字典中拉出的关键字来调用上述函数。在某些情况下,这很好(例如,如果您想将关键字传递给另一个函数)。在其他情况下,这不是你想要的。如果要在用户提供未知关键字时引发错误,可以执行以下操作:

def func(self,**kwargs):
    self.a=kwargs.pop('a',"Default_a")
    self.b=kwargs.pop('b',"Default_b")
    if(kwargs):  
        raise  ... #some appropriate exception...possibly using kwargs.keys() to say which keywords were not appropriate for this function.

答案 2 :(得分:3)

你可以这样做

def func(self, a=None):
    self.a = <some_initialisation> if a is None else a

但为什么要对一个衬垫进行痴迷?我通常会使用3行版本,即使它在整个地方重复使用,因为如果让经验丰富的Python程序员阅读代码非常容易

答案 3 :(得分:1)

我通过使用额外功能提出的一点解决方案,当然可以改进:

defaultargs.py:

    def doInit(var, default_value,condition):
        if condition:
            var = default_value
        return var

    def func(a=None, b=None, c=None):
        a =  doInit(a,5,(a is None or not isinstance(a,int)))
        b =  doInit(b,10.0,(a is None or not isinstance(a,float)))
        c =  doInit(c,"whatever",(a is None or not isinstance(c, str)))
        print a
        print b
        print c

    if __name__ == "__main__":
        func(10)
        func(None,12341.12)
        func("foo",None,"whowho")

输出:

    10
    10.0
    whatever
    5
    10.0
    whatever
    5
    10.0
    whowho

我喜欢你的问题。 :)

编辑:如果您不关心变量类型,请不要使用isinstance()。