Search code examples
pythonlistobjectsubclassbuilt-in-types

Redefining Pythons builtin datatypes


Is it possible to redefine which object the brackets [] use?

I can subclass the list object, but how to I make the interpreter use my subclass in place of the buildin list object? Is it possible?

(I'm pretty sure I'm using the wrong terms for the question- feel free to edit)

>>> class mlist(list):
...     def __init__(self):
...         list.__init__(self)
...     def __getitem__(self, item):
...         return list.__getitem__(self, item) * 2
... 
>>> testlist = mlist()
>>> testlist.append(21)
>>> testlist[0]
42
>>> list = mlist() # maybe setting the 'list' type will do it?
>>> testlist = []
>>> testlist.append(21)
>>> testlist[0]
21                 # Nope
>>> 

I don't have a practical use for this- just curious.


Solution

  • Try running the code after you've run the code you posted

    >>> testlist = list()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'mlist' object is not callable
    

    Now, determine the type using the code I've posted

    >>> type([])
    <type 'list'>
    >>> type(list)
    <class '__main__.mlist'>
    >>> type(testlist)
    <type 'list'>
    

    it seems that [] creates list, instead of mlist, it looks strange :S

    Update

    I checked the bytecode generated using dis, and the code below was generated

    >>> import dis # python's disassembler
    
    >>> def code1():
    ...     return []
    ...
    >>> dis.dis(code1)
      2           0 BUILD_LIST               0
                  3 RETURN_VALUE
    
    >>> def code2():
    ...     return list()
    ...
    >>> dis.dis(code2)
      2           0 LOAD_GLOBAL              0 (list)
                  3 CALL_FUNCTION            0
                  6 RETURN_VALUE
    

    It appears that list will invoke whatever is assigned to it, while [] will be converted to BUILD_LIST bytecode. It appears that [] is not translated to list, hence []'s behavior is stucked to creating list.

    Update 2

    Python class can be updated

    >>> class NewList(list):
    ...     pass
    ...
    >>> a = NewList()
    >>> a.append(23)
    >>> a[0]
    23
    >>> def double_getitem(self, key):
    ...     return list.__getitem__(self, key) * 2
    ...
    >>> NewList.__getitem__ = double_getitem
    >>> a[0]
    46
    

    Well, except for builtin classes, like list

    >>> list.__getitem__ = double_getitem
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: can't set attributes of built-in/extension type 'list'