如何简化下面这些代码,避免 copy?

2016-07-07 22:51:46 +08:00
 guyskk

我需要写很多的校验函数,这些校验函数都有 default=None, optional=False, desc=None这几个参数。

def int_validater(min=0, max=1024,
                  default=None, optional=False, desc=None):
    def validater(value):
        if value is None:
            if default is not None:
                return default
            elif optional:
                return None
            else:
                raise Invalid("required")
        try:
            v = int(value)
        except ValueError:
            raise Invalid("invalid int")
        if v < min:
            raise Invalid("value must >= %d" % min)
        elif v > max:
            raise Invalid("value must <= %d" % max)
        return v
    return validater


def bool_validater(default=None, optional=False, desc=None):
    def validater(value):
        if value is None:
            if default is not None:
                return default
            elif optional:
                return None
            else:
                raise Invalid("required")
        if isinstance(value, bool):
            return value
        else:
            raise Invalid("invalid bool")
    return validater

这些校验函数用法类似这样:

validater = int_validater(0,10,default=5)
validater(-1) # raise Invalid("value must >= %d" % min)
validater(20) # raise Invalid("value must <= %d" % max)

怎么简化代码,避免 copy? 我试了用装饰器,但是不能处理好参数顺序,装饰后的函数原型因该是下面这样:

wraped_validater(default=None, optional=False, desc=None,*args,**kwargs)

如果int_validater(0,10,default=5),这样 0 和 10 对应的是 optional 和 desc ,而不是*args 。

2910 次点击
所在节点    Python
10 条回复
am241
2016-07-07 23:00:00 +08:00
看前半段想说装饰器,结果被抢答否定了
suber
2016-07-07 23:04:34 +08:00
你指定名字传参
chevalier
2016-07-07 23:28:59 +08:00
有现成的轮子: voluptuous
shyling
2016-07-07 23:54:51 +08:00
不要用默认值的形式
def func(*args,**kwargs)靠解析 args,kwargs 试试
guyskk
2016-07-08 00:12:22 +08:00
@shyling 感谢,解决了

```
def handle_default_optional_desc(some_validater):
def wrapped_validater(*args, **kwargs):
default = kwargs.pop("default", None)
optional = kwargs.pop("optional", False)
desc = kwargs.pop("desc", None)
origin_validater = some_validater(*args, **kwargs)

def validater(value):
if value is None:
if default is not None:
return default
elif optional:
return None
else:
raise Invalid("required")
return origin_validater(value)
return validater

return wrapped_validater
```
guyskk
2016-07-08 00:13:02 +08:00
@guyskk 缩进全没了。。怎么贴代码啊
guyskk
2016-07-08 00:16:01 +08:00
guyskk
2016-07-08 00:16:51 +08:00
guyskk
2016-07-08 00:19:52 +08:00
ruanimal
2016-07-08 10:49:37 +08:00
你这个需要多重装饰器。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/291002

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX