在python中使变量不可继承

时间:2009-07-02 21:13:36

标签: python inheritance

有没有办法在python中使变量不可继承?如下例所示:B是A的子类,但我希望它有自己的SIZE值。

如果B没有覆盖SIZE,我是否可以获得引发错误(在__init__或getsize()上)?

class A:
   SIZE = 5
   def getsize(self): return self.SIZE

class B(A): pass

编辑:...继承getsize()方法......?

8 个答案:

答案 0 :(得分:8)

使用双下划线前缀:

(Emma澄清后删除了双下划线解决方案)

好的,你可以这样做:

class A:
    SIZE = 5
    def __init__(self):
        if self.__class__ != A:
            del self.SIZE

    def getsize(self):
        return self.SIZE

class B(A):
    pass

a = A()
print a.getsize()
# Prints 5

b = B()
print b.getsize()
# AttributeError: B instance has no attribute 'SIZE'

答案 1 :(得分:4)

如果你想让绝对确保A的子类覆盖SIZE,你可以使用A的元类来引发错误子类不会覆盖它(注意A这里是一个新式的类):

class ClassWithSize(type):
    def __init__(cls, name, bases, attrs):
        if 'SIZE' not in attrs:
            raise NotImplementedError('The "%s" class does not implement a "SIZE" attribute' % name)
        super(ClassWithSize, cls).__init__(name, bases, attrs)

class A(object):
    __metaclass__ = ClassWithSize

    SIZE = 5
    def getsize(self):
        return self.SIZE

class B(A):
    SIZE = 6

class C(A):
    pass

当您将上述内容放入模块并尝试导入它时,导入到达C类实现时将引发异常。

答案 2 :(得分:2)

如果元类吓到了你(我同情这种态度! - ),一个描述符可以工作 - 你甚至不必制作自定义描述符(虽然那个easy已经足够了),一个简单的好老财产也可以正常工作:

class A(object):

  @property
  def SIZE(self):
    if type(self) is not A:
      raise AttributeError("Class %s MUST explicitly define SIZE!" % 
                            type(self).__name__)

  def getsize(self):
    return self.SIZE

当然,这种方式只有当A的子类实例没有覆盖SIZE实际上试图使用 self.SIZE时,才会得到错误(元类方法有当创建A的错误子类时,提前给出错误的优点。)

答案 3 :(得分:1)

我可以添加的唯一方法是在hasattr(self.__class__, 'SIZE')的实现中使用getsize(),如果找不到该属性则抛出异常。类似的东西:

class A:
   SIZE = 5
   def getsize(self):
     klass = self.__class__
     if hasattr(klass, 'SIZE') and 'SIZE' in klass.__dict__:
       return self.SIZE
     raise NotImplementedError('SIZE is not defined in ' + klass.__name__)

由于派生类可以定义名为SIZE的方法而getsize无法检测到它,因此仍然缺少一些魔法。如果你愿意的话,你可以做一些type(klass.SIZE)魔术来过滤掉它。

答案 4 :(得分:0)

您可以像这样覆盖它:

class B(A):  
  SIZE = 6

答案 5 :(得分:0)

听起来你想要的是私人变量。在这种情况下,您需要这样做:

class A:
    __SIZE = 5
    def getsize(self): 
        return self.__SIZE

    def setsize(self,newsize):
        self.__SIZE=newsize

class B(A): 
    pass

答案 6 :(得分:0)

另一种方法可能是让A类和B类从第三类继承,而不是从另一类继承:

class X:
    def getsize(self):
        return self.SIZE
class A(X):
    SIZE = 5

class B(X): pass

a = A()
print a.getsize()
# Prints 5

b = B()
print b.getsize()
# AttributeError: B instance has no attribute 'SIZE'

答案 7 :(得分:0)

另一个常见习语是使用NotImplemented。可以把它想象成元类执行和单纯文档之间的中间地带。

class A:
   SIZE = NotImplemented

现在,如果子类忘记覆盖SIZE,则运行时错误将立即显而易见。