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/

Reply via email to