2

I'm trying to sort out how to get a python object to return a default value by simply calling the object itself. Basically, this is equivalent to a class 'default member' common to other languages (I remember using it way back in my VB days).

For example, suppose I create a SuperTuple() class that extends the basic Python tuple. If I call the object with no parameters, I want it to return the Python tuple, not a string representation (as __repr__()) does.

That is if my basic class looks like:

class SuperTuple():

    _tuple = ()

    def __init__(self, tuple):
        _tuple = tuple

I want the following behavior:

>>> a = SuperTuple((1,2,3))
>>> a._tuple
(1, 2, 3)
>>> a
(1, 2, 3)

I suspect there isn't a way to do it in Python without arbitrarily creating some 'default' class member that needs to be explicitly called, which somewhat defeats the purpose.

The advantage, of course, would be to be able to use it in other operations without having to mess with operator overloading and other related issues:

>>> a = Supertuple(1, 2, 3)
>>> b = a + (4, 5, 6)
>>> b
(1, 2, 3, 4, 5, 6)
>>> type(a)
<class 'SuperTuple'>
>>> type(b)
<class 'tuple'>
Joel Graff
  • 167
  • 15
  • 2
    Do note that in `a + (4, 5, 6)` `__repr__` is NOT called: [(see his for more info on what `repr` is for)](https://stackoverflow.com/questions/1984162/purpose-of-pythons-repr). Your "desired" behaviour does not account for the fact that when printing a variable on the console, it is **the console** that calls `__repr__` to obtain a string representation of the object – GPhilo Sep 26 '19 at 14:20
  • What exactly do you want? Your title asks about overriding `__repr__` but there is no attempt to do it in the body of the question. – sanyassh Sep 26 '19 at 15:06

2 Answers2

4

Python has no "default attribute", as VB or other languages may have.

It looks like you want to make SuperTuple a descendant of tuple, so that the object itself is just an extension of tuple:

class SuperTuple(tuple):
    pass

It will inherit all behaviour from tuple, including starting it with a default value:

>>> t = SuperTuple((1, 2, 3))
>>> t
(1, 2, 3)
>>> type(t)
__main__.SuperTuple

Edit: You can override other magic methods to include the behaviour you want, for example:

class SuperTuple(tuple):

    def __add__(self, other):
        return SuperTuple(tuple(self) + other)

>>> t = SuperTuple((1, 2, 3))
>>> t2 = t + (4, 5, 6)
>>> t2
(1, 2, 3, 4, 5, 6)
>>> type(t2)
__main__.SuperTuple
augustomen
  • 8,977
  • 3
  • 43
  • 63
  • To add to this, if you call `isinstance(t, tuple)` it will return `True` because it inherits the instance from the `tuple`-class. – Hampus Larsson Sep 26 '19 at 14:20
  • +1 because it's a great way to solve this. But does anyone know how to do it without inheritance? I think this "SuperTuple" was used just as an example, would be nice to complement this with the solution – Alexander Santos Sep 26 '19 at 14:24
  • This is the solution that I had originally envisioned. However, it fails my need because it forces me to override operators that are provided by default in the base type, regardless of any changes in implementation. Your example of implementing __add__() illustrates exactly what I wish to avoid. :) – Joel Graff Oct 03 '19 at 14:10
0

You can just inherit from tuple which keeps all the desired behaviour. If you want to be able to add an attribute, you cannot do it in __init__ as the instance already exists there, and it is immutable! So, you have to override __new__ which actually creates the instance:

class Supertuple(tuple):
    def __new__(cls, arg):
        self = super(Supertuple, cls).__new__(cls, arg)
        self._tuple = tuple(arg)
        return self

>>> s = Supertuple([1,2,3])
>>> s._tuple
(1, 2, 3)
>>> s
(1, 2, 3)
user2390182
  • 72,016
  • 6
  • 67
  • 89
  • Accepting this answer as it allows default operator implementations to 'pass through' in the subclass implementation. – Joel Graff Oct 03 '19 at 14:11