Search code examples
pythonuniontyping

pre-commit/pylint : two types possible for my input, but it doesn't get that in the instructions


This is the code I have so far, but my input can be a boolean or a list of size 2 (str and int). Here is part of the code :

        # In the function arguments
        structured: Union[List[bool], bool]
        grid: Union[List[bool], bool]
        
        # instructions
        if structured is False or grid is False:
            self.structured: bool = False
        else:
            self.structured = True
            self.eltType = structured[0]
            self.Lx = grid[0]
            self.Ly = grid[1]
            self.Lz = structured[1]

But I get the error :

error: Value of type "Union[List[bool], Literal[True]]" is not indexable  [index]

The thing is that the first if statement tackles the case when grid/structured are bool and the else when they are arrays.

My second question is how to annotate an array that contains a str and an int.

List[Union[str,int]]  # maybe ?

Solution

  • Your condition, if false, doesn't guarantee for type-narrowing purposes that either variable is a list, only that at least one of them equals False.

    Use a more explicit condition:

    self.structured: bool
    if isinstance(structured, list) and isinstance(structured, list):
         self.structured = True
         self.eltType = structured[0]
         self.Lx = grid[0]
         self.Ly = grid[1]
         self.Lz = structured[1]
    else:
        self.structured = False
    

    Since a value of True doesn't seem to make sense for either variable, consider a more constrained type like Optional[list[bool]] instead. Then you only have either None or a (not necessarily long enough) list.

    # In the function arguments
    structured: Optional[List[bool]]
    grid: Optional[List[bool]]
        
    self.structured: bool
    if structured is not None and grid is not None:
        # Both must be lists
        self.structured = True
        self.eltType = structured[0]
        self.Lx = grid[0]
        self.Ly = grid[1]
        self.Lz = structured[1]
    else:
        # One of them might be a list, but we'll ignore it.
        self.structured: bool = False