Несмотря на сомнительную ценность, следующий трюк сработает, если будет нормально поставить первый __slots__
в подкласс.
class A( object ):
__slots__ = ( 'a', )
class B( A ):
__slots__ = ()
@property
def a( self ):
try:
return A.a.__get__( self )
except AttributeError:
return 'no a set'
@a.setter
def a( self, val ):
A.a.__set__( self, val )
(Вы можете использовать свой собственный дескриптор, а не свойство.) С этими определениями:
>>> b = B()
>>> b.a
'no a set'
>>> b.a = 'foo'
>>> b.a
'foo'
Насколько я понимаю, __slots__
реализован со своим собственным дескриптором, поэтому другой дескриптор после __slots__
в том же классе просто перезапишет. Если вы хотите разработать эту технику, вы можете найти дескриптор кандидата в self.__class__.__mro__
(или начинать с instance
в вашем собственном __get__
).
Постскриптум
Хорошо ... хорошо, если вы действительно хотите использовать один класс, вы можете использовать следующую адаптацию:
class C( object ):
__slots__ = ( 'c', )
class MyDescriptor( object ):
def __init__( self, slots_descriptor ):
self.slots_descriptor = slots_descriptor
def __get__( self, inst, owner = None ):
try:
return self.slots_descriptor.__get__( inst, owner )
except AttributeError:
return 'no c'
def __set__( self, inst, val ):
self.slots_descriptor.__set__( inst, val )
C.c = MyDescriptor( C.c )
Если вы настаиваете на непостижимости, вы можете выполнить назначение в метаклассе или в декораторе класса.