'error: Incompatible return value type (got "Tuple[Tuple[float, float], ...]", expected "List[Any]")

Context

While trying to implement static typing, I'm experiencing some difficulties in specifying the return type of the following function:

def create_hexagon_coordinates(origin: tuple, unit: float, plot=False) -> list[Tuple[float,float]]:
    unit = 3**0.5
    mid_left = (float(-unit), 0.)
    top_left = (float(-unit / 2), float(unit**2 / 2))
    hexagon = (
        mid_left,
        top_left,
    )
    return hexagon

Output

The error message is:

error: Incompatible return value type (got "Tuple[Tuple[float, float], Tuple[float, float], Tuple[float, float], Tuple[float, float], Tuple[float, float], Tuple[float, float]]", expected "List[Any]")

Assumption

I thought it would be better to be more explicit than List[Any] by including the specification of the type of the elements in the list. However, if I include that, it also requires me to specify the length of the list (as it expects me to specify the complete type of all elements). Since all element types in the list are returned in the error message.

Even when I include List[Tuple[float,float]] with captital as shown here, the error becomes:

error: "List" expects no type arguments, but 1 given

error: Incompatible return value type (got "Tuple[Tuple[float, float], Tuple[float, float], Tuple[float, float], Tuple[float, float], Tuple[float, float], Tuple[float, float]]", expected "_ast.List")

Question

Hence, I would like to ask, is it recommended specifying the type of the elements in the list (if it is known and the same for each element), for lists (of indeterminate) length, and if yes, how does one do so?



Solution 1:[1]

I made multiple small errors, which led to the error message. A working solution is:

def create_hexagon_coordinates(
    origin: tuple, unit: float, plot=False
) -> list[tuple[float, float]]:

    """Creates a list of coordinates of a hexagon, with a horizontal line in
    the top and bottom. Top right coordinate is named A, mid right coordinate
    is named B, and clockwise onwards.

    :param origin: tuple: Optional parameter to set the origin of the hexagon.
    :param unit: float: Optional parameter to set the length of the standard
    unit.
    """
    if origin is None:
        origin = (0, 0)

    top_right: tuple[float, float] = (float(unit / 2), float(unit**2 / 2))
    mid_right: tuple[float, float] = (float(unit), 0.0)
    bottom_right: tuple[float, float] = (
        float(unit / 2),
        float(-(unit**2) / 2),
    )
    bottom_left: tuple[float, float] = (
        float(-unit / 2),
        float(-(unit**2) / 2),
    )
    mid_left: tuple[float, float] = (float(-unit), 0.0)
    top_left: tuple[float, float] = (float(-unit / 2), float(unit**2 / 2))
    hexagon: list[tuple[float, float]] = [
        top_right,
        mid_right,
        bottom_right,
        bottom_left,
        mid_left,
        top_left,
    ]

    if plot:
        figure(figsize=(8, 8), dpi=80)
        plt.xlim(-5, 5)
        plt.ylim(-5, 5)
        for point in hexagon:
            plt.scatter(point[0], point[1])
        plt.show()
    return hexagon
  1. As pointed out by thinkgruen in the comments, the hexagon object was created as a tuple instead of a list. So the list[tuple..] would not work regardless of what I would put inside of the square brackets.
  2. I misread the error line, I thought it was thrown on the return statement.
  3. I assumed the error was about a discrepancy between the -> List[..] and the actual returned object.
  4. Initially, I did not explicitly make all tuple elements of type float, which meant there were some int types inbetween. I did not notice this. However, I think that was the reason the error suggested the type any.
  5. By having all these mistakes staked on top of eachother, without being aware of these mistakes, I assumed I had to include an explicit length of the variable types in a list, even though all examples I found, only showed a single type for all elements in a list. This assumption was invalid.
  6. I tried using capitalised types, as I saw this in some examples. Yet that was not required.

So to conclude, if all elements in a list are of the same type, you can write list[sometype] where sometype is the type of each element in the list. I had to ensure that those types were indeed identical.

There are still two things not clear to me, and those are:

  1. What is the difference between capitalised types and uncapitalised types.
  2. Is it possible to specify a set of acceptable types in a list, for example, list[float,int].

However, these are separate questions.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1