Your solution looks unnecessarily complicated to solve your problem, unless there's more to it that is shown. Why not simply do this:
class MyObject(object):
def __init__(value, attrib=None):
self.__value = value
self.attrib = {} if attrib is None else attrib
def __str__(self):
return __value
d = {}
d['1'] = MyObject("123", {"name": "val"})
print d['1'] # prints "123"
print d['1'].attrib["name"] # prints "val"
As for why your code doesn't work, there are a few obvious problems.
From your calls in various special methods of
__dict__
, it appears thatMyDict
is meant to subclassdict
, so the definition should be:class MyDict(dict): ...
While not incorrect, it is better practice to use
super
rather than referring to the base class directly, sodict.__init__(self)
would becomesuper(MyDict, self).__init__()
anddict.__getitem__(self, key)
becomessuper(MyDict, dict).__getitem__(key)
.Your call to get sill work, but doesn't match the method specification. You should call it as
v.__get__(self, MyDict)
. However, the way you are using it actually makes__get__
redundant, and I think that this usage it where the main problem lies.In class
MyDescriptor
, early binding will give you unexpected results forattrib
. See my example above for a better way for declaring it.
I suspect that instead of a description, what you actually want is an object which looks like a string (for some definition of "looks like"), but has an attribute attrib
. To do this, there is no need to try to create a descriptor, which is intended for a different use case altogether. My example above gives a class which satisfies the requirement of an object which "looks like" a string, where "looks like" means it prints a string, but here is another which may be more like what you want:
class MyString(str):
def __init__(self, value, attrib=None):
super(MyString, self).__init__(value)
self.attrib = {} if attrib is None else attrib