> P.S. (IMHO) the type check here is not that necessary (at least in its > current state), as what we need to assert is not the relation to the > dict class but the support of the mapping protocol.... The type-check is basically correct - as you have discovered, type & object use the PyDict_* API internally (for speed reasons, as I understand it), so supporting the mapping API is not really sufficient for something assigned to __dict__. Changing this for exec is one thing, as speed of access to the locals dict isn't likely to have a major impact on the overall performance of such code, but I would expect changing class dictionary access code in a similar way would have a major (detrimental) performance impact. Depending on the use case, it is possible to work around the problem by defining __dict__, __getattribute__, __setattr__ and __delattr__ in the class. defining __dict__ sidesteps the type error, defining the other three methods then let's you get around the fact that the standard C-level dict pointer is no longer being updated, as well as making sure the general mapping API is used, rather than the concrete PyDict_* API. This is kinda ugly, but it works as long as any C code using the class __dict__ goes via the attribute access machinery and doesn't try to get the dictionary automatically supplied by Python by digging directly into the type structure. ===================== from UserDict import DictMixin class Dict(DictMixin): def __init__(self, dct=None): if dct is None: dct = {} self._dict = dct def __getitem__(self, name): return self._dict[name] def __setitem__(self, name, value): self._dict[name] = value def __delitem__(self, name): del self._dict[name] def keys(self): return self._dict.keys() class A(object): def __new__(cls, *p, **n): o = object.__new__(cls) super(A, o).__setattr__('__dict__', Dict()) return o __dict__ = None def __getattr__(self, attr): try: return self.__dict__[attr] except KeyError: raise AttributeError("%s" % attr) def __setattr__(self, attr, value): if attr in self.__dict__ or not hasattr(self, attr): self.__dict__[attr] = value else: super(A, self).__setattr__(attr, value) def __delattr__(self, attr): if attr in self.__dict__: del self.__dict__[attr] else: super(A, self).__delattr__(attr) Py> a = A() Py> a.__dict__._dict {} Py> a.xxx = 123 Py> a.__dict__._dict {'xxx': 123} Py> a.__dict__._dict['yyy'] = 321 Py> a.yyy 321 Py> a.__dict__._dict {'xxx': 123, 'yyy': 321} Py> del a.xxx Py> a.__dict__._dict {'yyy': 321} Py> del a.xxx Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 21, in __delattr__ AttributeError: xxx Py> a.__dict__ = {} Py> a.yyy Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 11, in __getattr__ AttributeError: yyy Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.skystorm.net
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4