On Thu, Apr 22, 2021 at 6:57 AM Paul Moore <p.f.moore@gmail.com> wrote:
On Thu, 22 Apr 2021 at 09:46, Chris Angelico <rosuav@gmail.com> wrote:
Maybe in some cases, the "smaller protocols" option is practical, but it would need to have a useful name. For instance, if it needs to be readable, iterable, closeable, and autocloseable via __enter__/__exit__, that's ... uhh.... a readable, iterable, closeable context manager? Not an improvement over "file-like object".
Note: I've not used protocols myself, so this is speculation.
Is the name of the protocol important? Specifically, if I do, in my code
class X(Protocol): def read(self): ... def __iter__(self): ... def close(self): ... def __enter__(self): ... def __exit__(self, exc_type, exc_val, exc_tb): ...
def my_fn(fileobj: X) -> None: # my stuff
That is not a very good example of a Protocol. If you google for best practices for interfaces in Go (#golang), you'll find they advocate for very narrow protocols—what they call "interfaces" we decided to call "protocols". Many (perhaps most) protocols in the Go standard library define a single method. I highly recommend reading up on how "interfaces" are used in Go to reason about how "protocols" should be used in Python (*) Cheers, Luciano (*) That reminded me of how I found Python. In 1998 I was using Perl, which had just started to support classes. So in the Perl mailing lists there were quite a few messages then about how classes were used in Python. After a few mentions, I read the Python tutorial and never looked back. On Thu, Apr 22, 2021 at 6:57 AM Paul Moore <p.f.moore@gmail.com> wrote:
On Thu, 22 Apr 2021 at 09:46, Chris Angelico <rosuav@gmail.com> wrote:
Maybe in some cases, the "smaller protocols" option is practical, but it would need to have a useful name. For instance, if it needs to be readable, iterable, closeable, and autocloseable via __enter__/__exit__, that's ... uhh.... a readable, iterable, closeable context manager? Not an improvement over "file-like object".
Note: I've not used protocols myself, so this is speculation.
Is the name of the protocol important? Specifically, if I do, in my code
class X(Protocol): def read(self): ... def __iter__(self): ... def close(self): ... def __enter__(self): ... def __exit__(self, exc_type, exc_val, exc_tb): ...
def my_fn(fileobj: X) -> None: # my stuff
would that not work? An argument is checked to see if it conforms with a protocol by confirming it has the right methods, not by name, inheritance or registration. And if you want, you can just call X "FileLike", it's only a local name so it won't clash with whatever other people (or you, in a different module) want to say is "file-like". Of course, that's incredibly verbose and messy, and it would result in a huge proliferation of throw-away protocol classes, which is probably not a good practice that we'd want to encourage, but it works.
IMO, the problem isn't that *technically* static typing excludes the more traditional duck typing, but rather that the design, approach and as a result the emerging "best practices" are focused around inheritance based (is that what people mean by "nominal"?) models, to the point where duck typing feels like an afterthought that you have to work to include.
I wonder whether type checkers could handle a "magic" type (let's call it DuckTyped for now :-)) which basically means "infer a protocol based on usage in this function". So if I do:
def my_fn(f: DuckTyped): with f: data = f.read() for line in f: print(line) f.close()
then the type checker would automatically build a protocol type like the one I defined above and use that as the type of f? That would make it much easier to include duck typed arguments in function signatures while keeping the benefits of static type checking.
I will say that at the moment, this doesn't bother me much personally. On the larger projects where I've used typing, we've been fine with class-based typing and haven't really needed anything more complex like protocols. On smaller projects, I just don't use typing at all. Whether this will change if I decide to introduce typing in more places, I don't know at the moment. I've also not really used typing for public APIs, where an over-restrictive type would be more of an issue.
Paul _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/EQDLTZDX... Code of Conduct: http://python.org/psf/codeofconduct/
-- Luciano Ramalho | Author of Fluent Python (O'Reilly, 2015) | http://shop.oreilly.com/product/0636920032519.do | Technical Principal at ThoughtWorks | Twitter: @ramalhoorg