views:

38

answers:

3

(All in ActivePython 3.1.2)

I tried to change the class (rather than instance) attributes. The __dict__ of the metaclass seemed like the perfect solution. But when I tried to modify, I got:

TypeError: 'dict_proxy' object does not support item assignment

Why, and what can I do about it?

EDIT

I'm adding attributes inside the class definition.

setattr doesn't work because the class is not yet built, and hence I can't refer to it yet (or at least I don't know how).

The traditional assignment doesn't work because I'm adding a large number of attributes, whose names are determined by a certain rule (so I can't just type them out).

In other words, suppose I want class A to have attributes A.a001 through A.a999; and all of them have to be defined before it's fully built (since otherwise SQLAlchemy won't instrument it properly).

Note also that I made a typo in the original title: it's __dict__ of a regular class, not a metaclass, that I wanted to modify.

+1  A: 

The creation of a large number of attributes following some rule smells like something is seriously wrong. I'd go back and see if there isn't a better way of doing that.

Having said there here is "Evil Code" (but it'll work, I think)

class A:
    locals()['alpha'] = 1

print A.alpha

This works because while the class is being defined there is a dictionary that tracks the local variables you are definining. These local variables eventually become the class attributes. Be careful with locals as it won't necessarily act "correctly." You aren't really supposed to be modifying locals, but it does seem to work when I tried it.

Winston Ewert
I explained a bit more about the context in the edits.
max
Scary. I guess I can do it, but it seems like a hack. Isn't there something I can do "above board"? Btw, these attributes are not numerous; they are just dynamically created as I parse the input. I think maybe what's making this messy is declarative syntax from SQLAlchemy
max
I accept this answer, since this is the best there is under my conditions... I agree though, I'll ditch the declarative syntax...
max
A: 

I'm not too familiar with how 3 treats dict but you might be able to circumvent this problem by simply inheriting the dictionary class like so:

class A(dict):
 def __init__(self,dict_of_args):
  self['key'] = 'myvalue'
  self.update(dict_of_args)
  # whatever else you need to do goes here...

A() can be referenced like so:

d = {1:2,3:4}
obj = A(mydict)
print obj['test'],obj[3]  # this will print myvalue and 4

Hope this helps.

krs1
It would work if I didn't have to follow SQLAlchemy specs which require the use of class attributes.
max
A: 

Instead of using the declarative syntax, build the table seperately and then use mapper on it. see http://www.sqlalchemy.org/docs/05/ormtutorial.html# I think there is just no good way to add computed attributes to class while defining it.

Alternatively, I don't know whether this will work but:

class A(object):
    pass
A.all_my_attributes = values

class B(declarative_base, A):
   pass 

might possibly work.

Winston Ewert