首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python中继承但不共享(静态)的类成员

Python中继承但不共享(静态)的类成员
EN

Stack Overflow用户
提问于 2011-05-04 05:19:32
回答 1查看 232关注 0票数 2

我正在编写一个小的验证应用程序接口,并初始化类的__init__方法中每个字段的约束。但是这个设置主要是针对类一次完成的。

代码语言:javascript
复制
class Demo(Validatable):

    def __init__(self):
        Validatable.__init__(self)
        self.count = 11

        # could be done at class level
        self.constrain_field("count", Max(9), Even())

但问题是,每个字段的约束都必须存储在某个地方,这样做的数据结构是继承的类Validatable的一部分。所以所有的派生类都将共享相同的数据结构,如果约束是在类级别设置的,那么什么都不应该发生!

代码语言:javascript
复制
class Demo(Validatable):

    # doesn't work!
    Validatable.constrain_field("count", Max(9), Even())

    def __init__(self):
        self.count = 11

是否有可能继承数据结构并在派生类中的类级别对其进行初始化,而不共享约束的数据结构?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-05-04 10:06:26

这个问题有两个部分。

  1. 如何在子类级别设置Validatable数据结构的值,而不是在继承的Validatable类中设置;和
  2. 如何定义constrain_field方法,以便在类初始化时调用一次,而不是每次创建实例时都调用。

对于(1),Validatable类的初始值设定项可以使用其__class__属性访问实例的类。例如:

代码语言:javascript
复制
class Validatable(object):
    def __init__(self):
        self.__class__.fieldName = "value for " + self.__class__.__name__

class Demo(Validatable):
    def __init__(self):
        super(Demo, self).__init__()

class Demo2(Validatable):
    def __init__(self):
        super(Demo2, self).__init__()

d = Demo()
d2 = Demo2()
print "Demo.fieldName = " + Demo.fieldName
print "Demo2.fieldName = " + Demo2.fieldName

此代码打印:

代码语言:javascript
复制
Demo.fieldName = value for Demo
Demo2.fieldName = value for Demo2

然后,可以将constrain_field方法定义为使用调用它的实例的__class__属性来设置必要的数据结构。

不幸的是,这一切都需要在设置数据结构之前创建类的实例,这也意味着每次创建实例时都会调用constrain_field方法。显然,最好在类初始化时执行此操作,这是问题的第(2)部分。

为了解决第(2)部分,我建议使用python decorators。考虑以下代码,它将Python property函数(用作装饰器)与名为constrain_field的自定义装饰器函数组合在一起

代码语言:javascript
复制
def Max(maxValue):
    def checkMax(value):
        return value <= maxValue
    checkMax.__doc__ = "Value must be less than or equal to " + str(maxValue)
    return checkMax

def Even():
    def checkEven(value):
        "Value must be even"
        return value%2 == 0
    return checkEven

def constrain_field(*constraints):
    def constraint_decorator(setter):
        def checkConstraints(self, value):
            ok = True
            for c in constraints:
                if not c(value):
                    ok = False
                    print "Constraint breached: " + c.__doc__
            if ok:
                setter(self, value)
        return checkConstraints
    return constraint_decorator

class Demo(object):
    def __init__(self):
        self._count = 2

    @property
    def count(self):
        return self._count

    @count.setter
    @constrain_field(Max(9), Even())
    def count(self, value):
        self._count = value

d = Demo()
print "Setting to 8"
d.count = 8
print "Setting to 9"
d.count = 9
print "Setting to 10"
d.count = 10
print "Count is now " + str(d.count)

它打印:

代码语言:javascript
复制
Setting to 8
Setting to 9
Constraint breached: Value must be even
Setting to 10
Constraint breached: Value must be less than or equal to 9
Count is now 8

通过以这种方式使用装饰器,所有初始化都在类的定义过程中完成一次。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5875834

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档