[Python-ideas] Override dict.__new__ to raise if cls is not dict; do the same for str, list, etc.

Neil Girdhar mistersheik at gmail.com
Thu Apr 21 01:33:24 EDT 2016


On Thu, Apr 21, 2016 at 1:15 AM Chris Angelico <rosuav at gmail.com> wrote:

> On Thu, Apr 21, 2016 at 2:33 PM, Neil Girdhar <mistersheik at gmail.com>
> wrote:
> > I think inheriting directly from dict is simply bad code because CPython
> > doesn't promise that any of your overridden methods will be called.  The
> > fact that it silently doesn't call them is an inscrutable trap.  And
> really,
> > it's not much of a "punishment" to simply change your base class name.
>
> There are way too many cases that work just fine, though.
>
> >>> class AutoCreateDict(dict):
> ...     def __missing__(self, key):
> ...         return "<autocreated %r>" % key
> ...
> >>> acd = AutoCreateDict()
> >>> acd["asdf"]
> "<autocreated 'asdf'>"
>
> Why should I inherit from UserDict instead? I have to import that from
> somewhere (is it in types? collections? though presumably your error
> message would tell me that), and then I have to contend with the fact
> that my class is no longer a dictionary.
>

Of course it's a dictionary.  It's an abc.Mapping, which is all a user of
your class should care about.  After all, it "quacks like a duck", which is
all that matters.

>
> >>> class AutoCreateUserDict(collections.UserDict):
> ...     def __missing__(self, key):
> ...         return "<autocreated %r>" % key
> ...
> >>> acud = AutoCreateUserDict()
> >>> acud["qwer"]
> "<autocreated 'qwer'>"
> >>> json.dumps(acd)
> '{}'
> >>> json.dumps(acud)
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "/usr/local/lib/python3.6/json/__init__.py", line 230, in dumps
>     return _default_encoder.encode(obj)
>   File "/usr/local/lib/python3.6/json/encoder.py", line 199, in encode
>     chunks = self.iterencode(o, _one_shot=True)
>   File "/usr/local/lib/python3.6/json/encoder.py", line 257, in iterencode
>     return _iterencode(o, 0)
>   File "/usr/local/lib/python3.6/json/encoder.py", line 180, in default
>     o.__class__.__name__)
> TypeError: Object of type 'AutoCreateUserDict' is not JSON serializable
>
>
That's a fair point, but it seems like a bug in JSON.  They should have
checked if it's an abc.Mapping imho.


> If you *do* push forward with this proposal, incidentally, I would
> recommend not doing it in __new__, but changing it so the class is no
> longer subclassable, as per bool:
>
> >>> class X(int): pass
> ...
> >>> class X(bool): pass
> ...
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: type 'bool' is not an acceptable base type
>

Good point.


>
> But I am firmly -1 on disallowing dict subclasses just because they
> aren't guaranteed to call all of your overridden methods.
>
> ChrisA
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "python-ideas" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/python-ideas/7nFQURLhlQY/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> python-ideas+unsubscribe at googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160421/434d69e6/attachment-0001.html>


More information about the Python-ideas mailing list