[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 08:42:00 EDT 2016


On Thu, Apr 21, 2016 at 9:44 PM, Michael Selik <mike at selik.org> wrote:
> On Thu, Apr 21, 2016 at 7:30 AM Steven D'Aprano <steve at pearwood.info> wrote:
>>
>> On Thu, Apr 21, 2016 at 04:36:54PM +1000, Nick Coghlan wrote:
>>
>> > Builtins can be extended, you just have to override all the methods
>> > where
>> > you want to change the return type:
>>
>> I wonder whether we should have a class decorator which automatically
>> adds the appropriate methods?
>
>
> If I'm not mistaken, some of the dunders need to be overridden as part of
> the class definition and can't be added dynamically without some exec a la
> namedtuple. If so, are you still interested in creating that decorator?

Which ones? __new__ is already covered, and AFAIK all operator dunders
can be injected just fine.

def operators_return_subclass(cls):
    if len(cls.__bases__) != 1:
        raise ValueError("Need to have exactly one base class")
    base, = cls.__bases__
    def dunder(name):
        def flip_to_subclass(self, other):
            x = getattr(super(cls, self), name)(other)
            if type(x) is base:
                return cls(x)
            return x
        setattr(cls, name, flip_to_subclass)
    for meth in "add", "sub", "mul", "div":
        dunder("__"+meth+"__")
    return cls

@operators_return_subclass
class hexint(int):
    def __repr__(self):
        return hex(self)

I'm not sure what set of dunders should be included though.

I've gone extra strict in this version; for instance, hexint/2 -->
float, not hexint. You could go either way.

ChrisA


More information about the Python-ideas mailing list