有没有办法在python中使变量不可继承?如下例所示:B是A的子类,但我希望它有自己的SIZE值。
如果B没有覆盖SIZE,我是否可以获得引发错误(在__init__或getsize()上)?
class A:
SIZE = 5
def getsize(self): return self.SIZE
class B(A): pass
编辑:...继承getsize()方法......?
答案 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,则运行时错误将立即显而易见。