在Python中使变量不可继承
有没有办法让一个变量在Python中不被继承?比如下面这个例子:B是A的子类,但我希望它有自己的SIZE值。
如果B没有重写SIZE,能不能在__init__或者getsize()的时候抛出一个错误?
class A:
SIZE = 5
def getsize(self): return self.SIZE
class B(A): pass
编辑: ... 在继承getsize()方法的情况下...?
8 个回答
2
如果元类让你感到害怕(我能理解这种感觉!),那么你可以试试描述符——你甚至不需要自己去写一个自定义的描述符(虽然这其实很简单),一个普通的属性也能很好地工作:
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
当然,这样的话,只有当一个没有重写 SIZE 的 A 类子类的实例真正去 使用 self.SIZE
时,你才会遇到错误(而元类的方法的好处在于,它能在创建一个错误的 A 类子类时就提前报错)。
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'
5
如果你想确保类的子类一定要重写
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
当你把上面的代码放在一个模块里并尝试导入时,当导入到