1

When I run this (2.7.3) I get this output:

'Slotted1' object has no attribute 'c'
attribute c added to <class '__main__.Slotted2'>

I don't understand the difference in behavior between Slotted1 and Slotted2. Can anyone explain?

from ctypes import *

class BracedStructure(Structure):
    def __init__(self, **args):
        super(BracedStructure,self).__init__(**args) 

class Slotted1(Structure):
    __slots__ = ['a','b']
    _fields_ = [('a',c_int8),('b',c_int8)]  
    def __init__(self, **args):
        super(Slotted1,self).__init__(**args)
    def attemptToAddField(self):
        self.c = '?'
        print 'attribute c added to %s' % self.__class__

class Slotted2(BracedStructure):
    __slots__ = ['a','b']
    _fields_ = [('a',c_int8),('b',c_int8)]  
    def __init__(self, **args):
        super(Slotted2,self).__init__(**args)
    def attemptToAddField(self):
        self.c = '?'
        print 'attribute c added to %s' % self.__class__

if '__main__' == __name__:
    s1 = Slotted1(a=1,b=2)
    try:
        s1.attemptToAddField()
    except AttributeError as e:
        print e

    s2 = Slotted2(a=1,b=2)
    try:
        s2.attemptToAddField()
    except AttributeError as e:
        print e
dbr
  • 165,801
  • 69
  • 278
  • 343
phunctor
  • 599
  • 3
  • 9
  • Where is the behavior of `_fields_` defined? I assume it's a ctypes thing? – bukzor Aug 05 '12 at 18:00
  • Nope, it's a Structure thing. – phunctor Aug 05 '12 at 20:04
  • That doesn't really answer the question. Where is the behavior of `Structure._fields_` defined? – bukzor Aug 06 '12 at 03:44
  • You want to set `__slots__` as empty-list on BracedStructure, or more likely, don't set slots anywhere. `__slots__` should be considered an implementation detail and a micro-optimization. Only use it if you have a need for extreme speed / memory efficiency, and can demonstrate a benefit from using `__slots__`. – bukzor Aug 06 '12 at 03:47
  • __slots__ is used to unduckify BracedStructure subclass instances. There's lots of communications infrastructure that won't know what to do with dynamic attributes. So it's rules enforcement rather than micro optimization. Apart from that, yep. – phunctor Aug 24 '12 at 14:26
  • Structure._fields_ is in the Structure implementation. That's deeper than I wanted to dig. The big picture is tightening up the validity checking on a collection of 865 (generated by code we can't touch) legacy classes. Substituting BracedStructure for Structure in the base class, and postprocessing the generated code – phunctor Aug 24 '12 at 14:28
  • to comply with BracedStructure subclassing requirements is working out well so far. – phunctor Aug 24 '12 at 14:37

2 Answers2

2

Check this out: http://docs.python.org/reference/datamodel.html#slots

When inheriting from a class without __slots__, the __dict__ attribute of that class will always be accessible, so a __slots__ definition in the subclass is meaningless.

It so happens that BracedStructure has no __slots__, so it overrules __slots__ declaration in Slotted2.

dbr
  • 165,801
  • 69
  • 278
  • 343
t.dubrownik
  • 12,464
  • 1
  • 17
  • 6
  • Oh wow. That's exactly at the right abstraction level for me to get it. But Ima read the reference datamodel too, I think that's the document I've been looking for. – phunctor Aug 05 '12 at 20:05
0

That's because Slotted2 inherited the __dict__ attribute from BracedStructure. So it will accept new arguments regardless of __slots__

JBernardo
  • 32,262
  • 10
  • 90
  • 115