Search code examples
pythondatamodel

Creating inmutable types in Python using __new__()


My question is pretty simple, I have:

class upperstr(str):
    def __new__(cls, arg):
        return str.__new__(cls, str(arg).upper())

Why, if my __new__() method is directly using an instance of an inmutable type (str), instances of my new type (upperstr) are mutable?

>>> s = str("text")
>>> "__dict__" in dir(s)
False
>>> s = upperstr("text")
>>> "__dict__" in dir(s)
True

In what stage does the interpreter sets the __dict__ attribute to upperstr intances if I'm only overriding the __new__() method?

Thanks!


Solution

  • All user-defined classes in Python have a __dict__() attribute by default, even if you don't overwrite anything at all:

    >>> x = object()
    >>> x.__dict__
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'object' object has no attribute '__dict__'
    >>> class MyObject(object):
    ...     pass 
    ... 
    >>> x = MyObject()
    >>> x.__dict__
    {}
    

    If you don't want a new-style class to have a __dict__, use __slots__ (documentation, related SO thread):

    >>> class MyObject(object):
    ...     __slots__ = []
    ... 
    >>> x = MyObject()
    >>> x.__dict__
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'MyObject' object has no attribute '__dict__'