Mattia Larentis
Mattia Larentis

Reputation: 302

Mypy list shadowing

I had a DRF (django-rest-framework) ViewSet class with some methods, and one of them is

def foobar(foo: list[str], bar: list[int]) -> bool:
    return ...

Today, when I implemented the def list method of the common ViewSet class, mypy started considering this new function instead the builtin list for the list[str] giving me some errors:

error: Function "path.to.the.class.list" is not valid as a type  [valid-type]
note: Perhaps you need "Callable[...]" or a callback protocol?
error: "list?[builtins.str]" has no attribute "__iter__" (not iterable)  [attr-defined]

The problem is clear, the new function does shadowing. The question is how do you usually avoid this problem? In my personal case find a solution is quiet easy, I can just move my function to another class / file / outside this class and everything will work as expected.

I would like to collect other ideas.

Upvotes: 2

Views: 526

Answers (2)

Luke-zhang-04
Luke-zhang-04

Reputation: 793

Well, list is a built-in in Python, and it's good practice not to override it, for this very reason. Your new list function overrides the existing one, and you won't be able to access the original function in the same file.

I would usually recommend you renaming your function to something else. However, this doesn't seem possible in your case.

Another option you can consider is importing the List type

from typing import List


def foobar(foo: List[str], bar: List[int]) -> bool:
    ...

A bit inconvenient, but it gets around your specific problem + it works the same way.

Edit: If you can't import List, you can make a type alias

listAlias = list


class MyClass:
    def list(self):
        ...

    def foobar(self, foo: listAlias[str], bar: listAlias[int]) -> bool:
        ...

Or you can import the builtins module like in Joel's answer

Upvotes: 1

joel
joel

Reputation: 7877

First choice is don't use builtin names for custom objects. If that's not possible, disambiguate with

import builtins

builtins.list[str]

or ClassName.list as appropriate

Upvotes: 1

Related Questions