Postpone creation of attributes until needed
Steven D'Aprano
steve at REMOVE.THIS.cybersource.com.au
Mon Jun 11 07:56:58 EDT 2007
On Mon, 11 Jun 2007 03:58:16 -0700, Frank Millman wrote:
>> By using slots, you're telling Python not to reserve space for a __dict__,
>> which means that your class cannot create attributes on the fly.
>>
>
> I understand that. In fact I was already using slots, as I was
> concerned about the number of 'column' instances that could be created
> in any one program, and wanted to minimise the footprint.
Unless you have thousands and thousands of instances, __slots__ is almost
certainly not the answer. __slots__ is an optimization to minimize the
size of each instance. The fact that it prevents the creation of new
attributes is a side-effect.
> I have since
> read some of caveats regarding slots, but I am not doing anything out
> of the ordinary so I feel comfortable with them so far.
>
>> > I use __slots__ to catch any invalid attributes, otherwise I would get
>> > a 'maximum recursion depth exceeded' error.
>>
>> That's the wrong solution to that problem. To avoid that problem,
>> __getattr__ should write directly to self.__dict__.
>>
>
> Are you saying that instead of
>
> self.z = self.x * self.y
> return getattr(self.name)
>
> I should have
>
> self.__dict__['z'] = self.x * self.y
> return self.__dict__[name]
>
> I tried that, but I get AttributeError: 'A' object has no attribute
> '__dict__'.
Of course you do, because you are using __slots__ and so there is no
__dict__ attribute.
I really think you need to lose the __slots__. I don't see that it really
gives you any advantage.
> Aslo, how does this solve the problem that 'name' may not be one of
> the attributes that my 'compute' method sets up. Or are you saying
> that, if I fixed the previous problem, it would just raise
> AttributeError anyway, which is what I would want to happen.
You haven't told us what the 'compute' method is.
Or if you have, I missed it.
>> > Is this ok, or is there a better way?
>>
>> At the interactive Python prompt:
>>
>> help(property)
>>
>
> See my reply to Phil - I would use property if there was only one
> attribute, but there are several.
Writing "several" properties isn't that big a chore, especially if they
have any common code that can be factored out.
Another approach might be to create a factory-function that creates the
properties for you, so you just need to call it like this:
class MyClass(object):
x = property_maker(database1, tableX, 'x', other_args)
y = property_maker(database2, tableY, 'y', other_args)
# blah blah blah
def property_maker(database, table, name, args):
def getx(self):
return getattr(database[table], name) # or whatever...
def setx(self, value):
setattr(database[table], name, value)
return property(getx, setx, None, "Some doc string")
--
Steven.
More information about the Python-list
mailing list