Pojo喜欢Python中的类

Lok*_*wal 0 python class

我想在Python中为User创建类似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")
Run Code Online (Sandbox Code Playgroud)

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

  1. 我的用户类将有大约50'属性.我有点害怕想象在这种情况下这个班级会有多大.

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

zwe*_*wer 6

我看不出有什么clumpsy这一点-如果你想要把所有的属性分为吸气-那里没有内置式的getter/setter验证,所以你最终会在你选择任何语言写一些类似的大多数语言/ setter与验证配对,你必须单独编写它们.

现在,Python是一种非常灵活的动态语言,因此有几种方法可以用来减少这个过程的冗长(但不是复杂性).例如,您可以创建自己的验证器装饰器,以便在您的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
Run Code Online (Sandbox Code Playgroud)

现在,您可以定义您的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
Run Code Online (Sandbox Code Playgroud)

但是,如果你只是在你的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)
Run Code Online (Sandbox Code Playgroud)

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

class User:

    age = ValidatingProperty("_age", lambda x: x < 0, ValueError("Age can't be negative"))

    def __init__(self, age):
        self.age = age
Run Code Online (Sandbox Code Playgroud)

如果您需要访问原始属性(假设它已设置),没有包装它,您仍然可以使用self._age(或者您作为第一个参数传递的任何'真实'属性)访问它ValidatingProperty.您甚至可以单独构建验证器,这样您就不必依赖lambdas(例如,创建一个IntegerValidator允许您传递范围以进行验证然后在需要时重用的类).

另一个选择是将您的类的用户视为成人,并解释文档中的有效值,如果他们超出了这一点 - 就会有龙.如果要使用来自最终用户的数据填充该类,则应在收集最终用户数据的一方执行验证(以便最终用户可以在考虑到这些数据时获得有意义的错误),而不一定在模型本身.