0

Why is it not possible to have an objects method return a tuple as argument in a new objects init method? Why does the following code not work and what needs to be done to make it work?

   class AcceptsTupleOnInit:
        def __init__(self,s,z):
            self.s = s
            self.z = z

    class ReturnsTuple:
        def return_tuple(self):
            return ("1", "2")

    r = ReturnsTuple()    
    a = AcceptsTupleOnInit(r.return_tuple())
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
jay123
  • 55
  • 9
  • 2
    Does this answer your question? [What does \*\* (double star/asterisk) and \* (star/asterisk) do for parameters?](https://stackoverflow.com/questions/36901/what-does-double-star-asterisk-and-star-asterisk-do-for-parameters) – Stephen Rauch Nov 10 '19 at 16:03

1 Answers1

2

AcceptsTupleOnInit doesn't take a tuple as an argument; it takes two separate arguments. You would need to unpack the tuple first.

a = AcceptsTupleOnInit(*r.return_tuple())

Alternatively, define __init__ to accept a tuple

def __init__(self, t):
    self.s = t[0]
    self.z = t[1]

or better, define an additional class method to unpack the tuple for you.

# usage:
# a = AcceptsTupleOnInit.from_tuple(r.return_tuple())
@classmethod
def from_tuple(cls, t):
    return cls(t[0], t[1])

In all three cases, it is your responsibility to provide a tuple with at least 2 values. The original definition of __init__ requires that return_tuple provide a tuple of exactly 2 elements; the modified __init__ and the class method are more flexible and will simply ignore additional elements. That's why I prefer the original __init__ (it's precise about what it requires and accepts) with a class method that can sanitize the input tuple as necessary. You can choose to ignore t[2:], or you can raise an exception if they are present.

chepner
  • 497,756
  • 71
  • 530
  • 681