pythontuplespython-typing

using tuple() on a list does not return an identical tuple according to typing


I created a class with a list attribute containing an int and a float. I then tried creating a getter method to return the list as a tuple.

from typing import Tuple, List

class MyClass:
    def __init__(self):
        self.__lst = [3, 5.0]

    def get_lst_as_tup(self) -> Tuple[int, float]:
        return tuple(self.__lst)

while it seems to work properly, PyCharm presents a problem:

Expected type 'Tuple[int, float]', got 'Tuple[Union[int, float], ...]' instead

after seeking stack overflow I tried several other implementations for the return statement. that resulted in the same error:

return (element for element in self.__lst)

return tuple(element for element in self.__lst)

return (*self.__lst,) this specific implementation resulted in :

Expected type 'Tuple[int, float]', got 'Tuple[Any]' instead

I was able to get rid of the error by using return self.__lst[0], self.__lst[1]

but I do not understand why it does not accept the other implementations.

Notes: I did not use the word tuple elsewhere in the file. This error occures even when this is all there is in the file.


Solution

  • For your example

    return (element for element in self.__lst)
    

    I doubt that you got the same error as this in fact returns a generator and not a tuple.

    Your other attempts

    return tuple(self.__lst)
    return (*self.__lst,)
    return tuple(element for element in self.__lst)
    

    are all valid approaches to convert the list self.__lst into a tuple. Of course, the most readable is tuple(self.__lst), so you should probably stick with this.

    I think the suggested type Tuple[Union[int, float], ...] is still too narrow here. You are converting a list which is of variable length into a tuple. There is no way of knowing which length self.__lst will have in your program. Consider this:

    m = MyClass()
    m._MyClass__lst.append("hello")
    r = m.get_lst_as_tup()
    print(r)
    

    Output: (3, 5.0, 'hello')

    Which is of type Tuple[int, float, str].

    However, when you use return self.__lst[0], self.__lst[1] it is guaranteed that the function will return a tuple of length 2 (or throw an exception if the list became smaller than length 2).