-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SubType and SubInstance #2169
Comments
I guess I found solution: import abc
from typing import Type, TypeVar
class BaseABC(abc.ABC):
@abc.abstractmethod
def foo(self) -> None:
pass
class Foo(BaseABC):
def foo(self):
pass
Base = TypeVar('Base', bound=BaseABC)
def make_obj(cls: Type[Base]) -> Base:
inst = cls()
return inst
make_obj(Foo) But maybe open new bugs:
|
What if you do: T = TypeVar('T', bound=Base)
def make_obj(cls: Type[T]) -> T:
inst = cls() # line 15
return inst |
IIRC we have another bug for this issue already. IMO mypy should not forbid
construction of an abstract class if the class is an argument declared
using Type[] -- it should assume you are passing it a concrete class. But
maybe we need a check that you call this thing with a concrete subclass;
and for that we would need some additional notation (unless maybe we could
just say that whenever there's an argument of Type[A] where A is abstract,
that the argument must be a concrete subclass. But for that we'd need some
experiment to see if there's much real-world code that passes abstract
classes around. (If there is, we'd need to have a way to indicate the need
in the signature.)
|
I just stumbled upon this while implementing a generic parser over concrete types of an abstract base class. So, there is an actual real-world use case for this. Basically, the following should type check flawlessly in my opinion: import abc
import typing
class Base(metaclass=abc.ABCMeta):
@abc.abstractmethod
def foo(self) -> None:
raise NotImplementedError
def Concrete(Base):
def foo(self) -> None:
print('bar')
def create(cls: typing.Type[Base]) -> Base:
return cls() |
Agreed. --Guido (mobile) On Sep 23, 2016 7:58 AM, "Oliver Mader" notifications@github.com wrote:
|
I don't understand why should it typecheck. It looks unsafe to me. |
@elazarg Mypy doesn't need to flag everything that looks unsafe. It must be a useful tool, and some code that is theoretically unsafe is both common and useful in practice and the unsafe scenario never occurs, so complaining about it is unhelpful. In general there is no single concrete subclass of an ABC like Base in the example, so there is no easy way to state "any concrete subclass of Base". I would much rather have an occasional unsafe piece of code pass without error (a false negative) than require users to add extra markup to code that is almost always fine in practice (a false positive), if the annoyance of false positives outweighs the cost of false negatives. This is one of those cases. This is a different philosophy from most typed languages, and it is Python's runtime type checking that gives us this luxury. |
I am not sure that in practice unsafe scenarios never occur. It is not unlikely to forget adding an override to a new abstract method, and this is the place where it can be caught. I understand the reasoning however: it is unsafe, but not yet possible to express in a useful way, so we err towards flexibility, avoiding false positives. Fair enough. (The reason I say "yet" relates to my pending proposal in python-ideas. An easy and clear way to write it would be def create(cls: typing.Type[Base] and cls(...) ) -> Base:
return cls() It is easily understood but unfortunately not reasonable to use as things currently stand) |
This is a dup of #1843. |
Hi,
I trying check with mypy following code:
And got errors:
I want have some expression for define that variable type is one of subclasses of
Base
but notBase
, somethink like this:Is it possible now?
The text was updated successfully, but these errors were encountered: