Reputation: 302
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
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
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