[Python-ideas] Override dict.__new__ to raise if cls is not dict; do the same for str, list, etc.
Chris Angelico
rosuav at gmail.com
Thu Apr 21 22:13:00 EDT 2016
On Fri, Apr 22, 2016 at 12:00 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> On Thu, Apr 21, 2016 at 09:43:17AM -0400, Random832 wrote:
>> On Thu, Apr 21, 2016, at 07:17, Steven D'Aprano wrote:
>> > and it runs counter to a documented feature of dicts, that they can be
>> > subclassed and given a __missing__ method:
>> >
>> > "If a SUBCLASS OF DICT [emphasis added] defines a method __missing__()
>> > and key is not present, the d[key] operation calls that method ..."
>>
>> So what method should be overridden to make a dict subclass useful as a
>> class or object dictionary (i.e. for attribute lookup to work with names
>> that have not been stored with dict.__setitem__)?
>
> I don't understand your question. Or rather, if I have understood it,
> the question has a trivial answer: you don't have to override anything.
>
> class MyDict(dict):
> pass
>
> d = MyDict()
> d.attr = 1
> print(d.attr)
>
>
> will do what you appear to be asking. If that's not what you actually
> mean, then you need to explain more carefully.
"As a class or object dictionary". Consider:
>>> class X: pass
...
>>> X().__dict__
{}
>>> type(_)
<class 'dict'>
Now, what can I replace that with? A regular dict works fine:
>>> x = X()
>>> x.__dict__ = {"asdf": 1}
>>> x.asdf
1
But defining __missing__ doesn't create attributes automatically:
>>> class AutoCreateDict(dict):
... def __missing__(self, key):
... return "<%r>" % key
...
>>> x.__dict__ = AutoCreateDict()
>>> x.qwer
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'X' object has no attribute 'qwer'
And neither does overriding __getitem__:
>>> class OtherAutoCreateDict(dict):
... def __getitem__(self, key):
... try: return super().__getitem__(key)
... except KeyError: return "<%r>" % key
...
>>> x.__dict__ = OtherAutoCreateDict()
>>> x.zxcv
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'X' object has no attribute 'zxcv'
The question is a fair one. What can you do to make an object's
dictionary provide attributes that weren't put there with __setitem__?
ChrisA
More information about the Python-ideas
mailing list