My personal motivating example for PEP 637 was shorthand for protocols. `x: Protocol[foo=int, bar=Callable[str, int]]` could say x has attribute foo which is an int and method bar from str to int.
On Wed, Apr 21, 2021 at 4:23 PM Paul Bryan <pbr...@anode.ca> wrote: > I agree, that's duck typing with a protocol, and precisely the tedious > type style I would want to avoid. > > I don't know what would be a good suggestion. Something where you > reference a "fully equipped" type and cherry pick the attributes you want? > Something like `Protocol[Duck, ("quack", "waddle")]`? > > Paul > > > On Wed, 2021-04-21 at 16:13 -0700, Jelle Zijlstra wrote: > > > > El mié, 21 abr 2021 a las 15:30, Paul Bryan (<pbr...@anode.ca>) escribió: > > As demonstrated, protocols don't get us there because duck typing isn't a > matter of having an object exhibit all of the attributes of a duck, but > rather some subset of attributes to be used by the consumer. I want this > duck to quack; someone else will want it to waddle. I don't see how type > hints could reasonably support "file like object" in the duck type sense > (unless the consumer were to specify the exact attributes of the duck it's > interested in, which I fear would become a tedious type writing style). ' > > > This approach (a Protocol that declares exactly what you need the > file-like object to do) is in fact what we've been doing in typeshed, the > repository that provides type hints for the standard library. For those > unfamiliar, it would look something like this: > > from typing import Protocol > > class SupportsRead(Protocol): > def read(self) -> bytes: ... > > def uses_a_file(f: SupportsRead) -> None: > f.read() > > That's somewhat tedious, to be sure, but it is working duck typing. > > > > I too have sensed static typing driving the typing development agenda in > Python recently, causing other typing methods to take a back seat, so to > speak. I add my voice to those requesting Python handle other typing > methods. > > Barring an innovation to allow a "subset" of a type to be declared in a > type hint, I would conclude that static typing and duck typing are > diametrically opposed. If we agree that both are valuable, developers could > build consensus on that point, and work to ensure that one does not move > forward at the expense of the other. > > What would you suggest? Should the syntax for declaring Protocols be more > concise? > > > > Paul > > On Wed, 2021-04-21 at 12:36 -0700, Christopher Barker wrote: > > Thanks Mark for posting this. I know some of us are uneasy about the pace > of the typing train .... > > On Tue, Apr 20, 2021 at 11:20 AM Nathaniel Smith <n...@pobox.com> wrote: > > > If you guarded your code with `isinstance(foo, Sequence)` then I could > > not use it with my `Foo` even if my `Foo` quacked like a sequence. I was > > forced to use nominal typing; inheriting from Sequence, or explicitly > > registering as a Sequence. > > You say this like it's a bad thing, but how is this avoidable, even in > principle? Structural typing lets you check whether Foo is duck-shaped > -- has appropriate attribute names, etc. But quacking like a duck is > harder: you also have to implement the Sequence behavioral contract, > and realistically the only way to know that is if the author of Foo > tells you. > > > But that's not what duck typing is (at least to me :-) ) For a given > function, I need the passed in object to quack (and yes, I need that quack > to sound like a duck) -- but I usually don't care whether that object > waddles like a duck. > > So yes, isinstance(obj, Sequence) is really the only way to know that obj > is a Sequence in every important way -- but if you only need it to do one > or two things like a Sequence, then you don't care. > > And this is not uncommon -- I suspect it's very rare for a single function > to use most of the methods of a given ABC (or protocol, or whatever). > > And a lot of the standard library works exactly this way. Two examples > (chosen arbitrarily, I just happen to have thought about how they work): > > json.load() simply calls ``fp.read()``, and passes the result on down to > json.loads(). That's it -- no checking of anything. > > If fp does not have a read() method, you get an AttributeError. If fp has > a read() method, but it returns something other than a string, then you get > some other Exception. And if it returns a string, but that string isn't > valid JSON, you get yet another kind of error. > > In short, json.load(fp, ...) requires fp to have a read() method that > returns a valid JSON string. But it doesn't check, nor does it need to, if > it's getting an actual io.TextIOBase object. Is that the right one? I'm not > totally sure, which I kind of think makes my point -- I've been using > "file-like" objects for years (decades) without worrying about it. > > Example 2: > > The str.translate method takes: > > "a mapping of Unicode ordinals to Unicode ordinals, strings, or None" > > Ok, then you need to pass in a Mapping, yes? Well, no you don't. The docs > go on to say: > > The table must implement lookup/indexing via __getitem__, for instance a > dictionary or list. > > Ah -- so we don't need a Mapping -- we need anything indexable by an > integer that contains "ordinals, strings, or None". What the heck ABC could > we use for that? > > The ABCs do have an already complex hierarchy of containers, but there is > no "Indexable", (quacks) and certainly no "indexable and returns these > particular things. (quacks a certain way). (maybe there's something in the > typing module that would work for static typing -- I have no idea). > > I'm pretty sure this particular API was designed to accommodate the old > py2 str.translate, which took a length-256 sequence, while also > accommodating full Unicode, which would have required a 2^32 length > sequence to do the same thing :-) > > But again -- this is duck typing, built into the stdlib, and it works > just fine. > > Granted, until PEP 563 (kind of) , there has been nothing that weakens or > disallows such duck typing -- those of us that want to write fully > duck-typed code can continue to do so. > > But there is the "culture" of Python -- and it has been very much shifting > toward more typing -- A recent publication (sorry can't find it now -- my > google fu is failing me) examined code on PyPi and found a lot of type > hints -- many of which were apparently not being used with a static type > checker. So why were they there? > > And I've seen a lot more isinstance(Some_ABC) code lately as well. > > From looking at the work of my beginning students, I can tell that they > are seeing examples out there that use more typing, to the point that they > think it's a best practice (or maybe even required?). Maybe it is -- but if > the community is moving that way, we should be honest about it. > > > I'm not even sure that this *is* nominal typing. You could just as > well argue that "the operation `isinstance(..., Sequence)` returns > `True`" is just another of the behavioral constraints that are > required to quack like a sequence. > > > I'm not sure of the definition of "nominal" typing -- but it absolutely is > NOT duck typing (As Luciano pointed out, Alex Martelli coined the term > Goose Typing for this). > > The big distinction is whether we want to know if the object is a duck, or > if we only need it to do one or two things like a duck. > > -CHB > > > _______________________________________________ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@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/ZXI3RTBVW44WGX44D4OFSH6GXL3SYPVO/ > Code of Conduct: http://python.org/psf/codeofconduct/ > > > _______________________________________________ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@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/PDW6UUK2QFS3J6B6SIQGUE2E7J7IELIS/ > Code of Conduct: http://python.org/psf/codeofconduct/ > > > _______________________________________________ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@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/HY6XET253F6XCSZGPNXESYL3KPOUXI6E/ > Code of Conduct: http://python.org/psf/codeofconduct/ >
_______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@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/22F733O3KADULPVRDQPHZBTOGMIOYMQF/ Code of Conduct: http://python.org/psf/codeofconduct/