python: manipulating __dict__ of the class
(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).
T开发者_Python百科he 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.
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.
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.
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.
精彩评论