<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Sep 10, 2015 at 11:57 AM, Matthias Kramm via Python-ideas <span dir="ltr"><<a href="mailto:python-ideas@python.org" target="_blank">python-ideas@python.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><span class="">On Wednesday, September 9, 2015 at 1:19:12 PM UTC-7, Guido van Rossum wrote:<blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Jukka wrote up a proposal for structural subtyping. It's pretty good. Please discuss.<br><br><a href="https://github.com/ambv/typehinting/issues/11#issuecomment-138133867" rel="nofollow" target="_blank">https://github.com/ambv/typehinting/issues/11#issuecomment-138133867</a></div></blockquote><div><br></div></span><div>I like this proposal; given Python's flat nominal type hierarchy, it will be useful to have a parallel subtyping mechanism to give things finer granularity without having to resort to ABCs.</div><div><br></div><div>Are the return types of methods invariant or variant under this proposal?</div><div><br></div><div>I.e. if I have</div><div><br></div><div>  class A(Protocol):</div><div>    def f() -> int: ...</div><div><br></div><div>does</div><div><br></div><div>  class B:</div><div>    def f() -> bool:</div><div>      return True</div><div><br></div><div>implicitly implement the protocol A?</div></div></blockquote><div><br></div><div>The proposal doesn't spell out the rules for subtyping, but we should follow the ordinary rules for subtyping for functions, and return types would behave covariantly. So the answer is yes.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>Also, marking Protocols using subclassing seems confusing and error-prone.</div><div>In your examples above, one would think that you could define a new protocol using</div><div><br></div><div>class SizedAndClosable(Sized):</div><div>    pass</div><div><br></div><div>instead of</div><div><br></div><div>class SizedAndClosable(Sized, Protocol):</div><div>    pass</div><div><br></div><div>because Sized is already a protocol.</div></div></blockquote><div><br></div><div>The proposal also lets you define the protocols implemented by your class explicitly, and without having the explicit Protocol base class or some other marker these would be impossible to distinguish in general. Example:</div><div><br></div><div>class MyList(Sized):   #  I want this to be a normal class, not a protocol.</div><div>    def __len__(self) -> int:</div><div>        return self.num_items</div><div> </div><div>class DerivedProtocol(Sized):  # This should actually be a protocol.</div><div>    def foo(self) -> int: ...</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>Maybe the below would be a more intuitive syntax:</div><div><br></div><div>  @protocol</div><div>  class SizedAndClosable(Sized):</div><div>      pass</div><div><br></div></div></blockquote><div> </div><div>We could use that. The tradeoff it that then we'd have some inconsistency depending on whether a protocol is generic or not:</div><div><br></div><div>@protocol</div><div>class A(metaclass=ProtocolMeta):   # Non-generic protocol</div><div>    ...</div><div><br></div><div>@protocol</div><div>class B(Generic[T]):   # Generic protocol. But this has a different metaclass than the above?</div><div>    ...</div><div><br></div><div>I'm not sure if we can use ABCMeta for protocols as protocols may need some additional metaclass functionality. Anyway, any proposal should consider all these possible ways of defining protocols:</div><div><br></div><div>1. Basic protocol, no protocol inheritance</div><div>2. Generic protocol, no protocol inheritance</div><div>3. Basic protocol that inherits one or more protocols</div><div>4. Generic protocol that inherits one or more protocols</div><div><br></div><div>My approach seems to deal with all of these reasonable well in my opinion (but I haven't implemented it yet!), but the tradeoff is that the Protocol base class needs to be present for all protocols.</div><div><br></div><div>Jukka</div></div></div></div>