代码之家  ›  专栏  ›  技术社区  ›  Lokesh Agrawal

python中类似pojo的类

  •  0
  • Lokesh Agrawal  · 技术社区  · 7 年前

    我想在python中为用户创建一个类似pojo的类。每个属性都将涉及一些验证。例如:我不希望有人创建一个年龄值为负的用户。我最后会写一个类似下面的课。

     class User:
            def __init__(self, age):
                self.age = age
    
            @property
            def age(self):
                return self._age
    
            @age.setter
            def age(self, value):
                print("Called")
                if value >= 0:
                    self._age = 0
                else:
                    raise ValueError("Age can't be negative")
    

    看到上面的课我有点害怕。原因:

    1. 我的用户类大约有50个属性。我有点害怕想象在这种情况下这门课会有多大。

    这是在Python中创建此类类的正确方法吗?

    1 回复  |  直到 7 年前
        1
  •  5
  •   zwer    7 年前

    我不知道是什么 笨拙的 关于这一点,目前大多数语言都没有内置的getter/setter验证,因此您最终会用任何语言编写类似于此的内容-如果您希望通过验证将所有属性转换为getter/setter对,则必须分别编写它们。

    现在,python是 非常 灵活的性质,所以有几种方法可以用来减少这个过程的冗长性(但不是复杂性)。例如,您可以创建自己的validator decorator,将其夹在setter的顶部,例如:

    def validator(cmp, exc):
        def decorator(setter):  # a decorator for the setter
            def wrapper(self, value):  # the wrapper around your setter
                if cmp(value):  # if cmp function returns True, raise the passed exception
                    raise exc
                setter(self, value)  # otherwise just call the setter to do its job
            return wrapper
        return decorator
    

    现在您可以定义getter/setter对,其中验证包括:

    class User:
    
        def __init__(self, age):
            self.age = age
    
        @property
        def age(self):
            return self._age
    
        @age.setter
        @validator(lambda x: x < 0, ValueError("Age can't be negative"))
        def age(self, value):
            self._age = value
    

    但是,如果您只打算在setter(和getter)中进行验证,而不进行其他处理,那么您可以定义自己的 验证 属性并节省大量的冗长信息,例如:

    class ValidatingProperty(object):
    
        def __init__(self, prop, cmp, exc):
            self.prop = prop
            self.cmp = cmp
            self.exc = exc
    
        def __get__(self, instance, owner=None):
            if instance is None:
                return self
            return getattr(instance, self.prop, None)
    
        def __set__(self, instance, value):
            if self.cmp(value):
                raise self.exc
            setattr(instance, self.prop, value)
    
        def __delete__(self, instance):
            delattr(instance, self.prop)
    

    现在,您可以简单地构建类getter/setter,如下所示:

    class User:
    
        age = ValidatingProperty("_age", lambda x: x < 0, ValueError("Age can't be negative"))
    
        def __init__(self, age):
            self.age = age
    

    如果需要访问原始属性(假设已设置),则 包装纸 围绕着它,你仍然可以用 self._age (或任何你作为第一个论点传递给你的“不动产” ValidatingProperty )甚至可以单独构建验证器,这样就不需要依赖lambda(例如,创建 IntegerValidator 类,它允许您通过验证范围,然后在需要时重用)。

    另一种选择是将类的用户视为成年人,并解释文档中的有效值,如果他们超出了这个范围,那么就有龙了。如果类打算用来自最终用户的数据填充,那么应该在收集最终用户数据的一侧执行验证(以便最终用户能够记住有意义的错误),而不一定是在模型本身中。